Невозможно создать статическую ссылку на нестатический метод

102

Создание многоязычного приложения на Java. Получение ошибки при вставке значения String из R.stringXML-файла ресурса:

public static final String TTT =  (String) getText(R.string.TTT);

Это сообщение об ошибке:

Ошибка: невозможно создать статическую ссылку на нестатический метод getText (int) из типа Context

Как это вызвано и как я могу это решить?

Чен М
источник
1
Зачем вам нужно, чтобы он был статическим для «многоязычного приложения»? Не совсем понимаю.
xil3
3
Никогда не храните строковые ресурсы в статических элементах данных. Всегда запрашивайте их через, getString()когда они вам нужны. Таким образом, ваше приложение правильно адаптируется к изменению пользователем выбранного языка.
CommonsWare

Ответы:

143

Поскольку getText()он нестатичен, вы не можете вызвать его из статического метода.

Чтобы понять почему, вы должны понимать разницу между ними.

Экземплярные (нестатические) методы работают с объектами определенного типа (класса). Они создаются с помощью нового, например:

SomeClass myObject = new SomeClass();

Чтобы вызвать метод экземпляра, вы вызываете его в instance ( myObject):

myObject.getText(...)

Однако статический метод / поле может быть вызван только для типа напрямую, скажем так: Предыдущий оператор неверен. Можно также ссылаться на статические поля со ссылкой на объект, например, myObject.staticMethod() но это не рекомендуется, потому что это не дает понять, что они являются переменными класса.

... = SomeClass.final

И они не могут работать вместе, поскольку работают с разными пространствами данных (данные экземпляра и данные класса).

Позвольте мне попытаться объяснить. Рассмотрим этот класс (псевдокод):

class Test {
     string somedata = "99";
     string getText() { return somedata; } 
     static string TTT = "0";
}

Теперь у меня есть следующий вариант использования:

Test item1 = new Test();
 item1.somedata = "200";

 Test item2 = new Test();

 Test.TTT = "1";

Какие ценности?

Хорошо

in item1 TTT = 1 and somedata = 200
in item2 TTT = 1 and somedata = 99

Другими словами, TTTэто данные, общие для всех экземпляров типа. Так что нет смысла говорить

class Test {
         string somedata = "99";
         string getText() { return somedata; } 
  static string TTT = getText(); // error there is is no somedata at this point 
}

Возникает вопрос, почему TTT статический или почему getText () не статический?

Удалите, staticи эта ошибка должна исчезнуть, но, не понимая, что делает ваш шрифт, это всего лишь липкая пластырь до следующей ошибки. Каковы требования getText(), чтобы он был нестатичным?

Preet Sangha
источник
он статичен, потому что я вызываю его из нескольких файлов в моем проекте. когда я удалил «статику», код ошибки исчез, но теперь у меня много ошибок в других файлах, использующих эту переменную.
Chen M
Но это моя точка зрения. Вы должны понимать, когда можно использовать и то, и другое.
Preet Sangha
когда я добавляю строку «Константы notifications_values ​​= new Constants (); в мой основной класс активности, он компилируется нормально, но в эмуляторе происходит сбой при выполнении этого действия»
Чен М.
12

Уже есть несколько хороших ответов с объяснением того, почему смесь нестатических Contextметодов getText()не может использоваться с вашим static final String.

Хороший вопрос: почему вы хотите это сделать? Вы пытаетесь загрузить Stringиз своего stringsресурса и ввести его значение в public staticполе. Я предполагаю, что это так, что некоторые из ваших других классов могут получить к нему доступ? Если да, то в этом нет необходимости. Вместо этого передайте Contextв другие классы и вызывайте context.getText(R.string.TTT)из них.

public class NonActivity {

    public static void doStuff(Context context) {
        String TTT = context.getText(R.string.TTT);
        ...
    }
}

И вызвать это из своего Activity:

NonActivity.doStuff(this);

Это позволит вам получить доступ к вашему Stringресурсу без необходимости использовать public staticполе.

dave.c
источник
1
спасибо большое, поменял все файлы по вашей рекомендации.
Chen M
Я пытался сделать это, но для массива строк и с String a[] = context.getTextArray(R.array.myStringArray); ; однако это дает мне ошибку The method getTextArray(int) is undefined for the type Context- почему он должен быть undefined, если он работает с getText?
auspicious99
1
@ auspicious99 просто потому, что у a Contextнет вызываемого метода getTextArray, но он есть getText. Возможно, вы думаете о том, Resourcesчто естьgetTextArray
dave.c
Ах, спасибо! Передал ресурсы вместо контекста (от активности до бездействия), и мой getStringArray работал.
auspicious99
9

для других, которые находят это в поиске:

Я часто получаю это, когда случайно вызываю функцию, используя имя класса, а не имя объекта. Обычно это происходит потому, что я даю им слишком похожие имена: P

то есть:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Очевидно, что это статический метод. (кое-что хорошо) Но то, что я действительно хотел сделать (в большинстве случаев было)

myclass.someFunction();

Это такая глупая ошибка, но каждые пару месяцев я трачу около 30 минут на возню с vars в определениях «MyClass», чтобы выяснить, что я делаю не так, хотя на самом деле это просто опечатка.

Забавное примечание: переполнение стека подчеркивает синтаксис, чтобы сделать ошибку здесь действительно очевидной.

SpiRail
источник
Разве ваша IDE не выделяет это тоже? Думаю, вы можете настроить его для этого :)
Маттиас Мейд
2

Вы можете сделать свою переменную нестатической

public final String TTT =  (String) getText(R.string.TTT);

или сделайте метод getText статическим (если это вообще возможно)

Келлиндил
источник
2

getText является членом вашей Activity, поэтому он должен вызываться, когда существует "this". Ваша статическая переменная инициализируется, когда ваш класс загружается до создания вашей Activity.

Поскольку вы хотите, чтобы переменная инициализировалась из строки ресурса, она не может быть статической. Если вы хотите, чтобы он был статическим, вы можете инициализировать его значением String.

Робби Пруд
источник
2

Вы не можете ссылаться на статическую переменную из нестатического метода. Чтобы понять это, вам нужно понять разницу между статикой и нестатикой.

Статические переменные - это переменные класса, они принадлежат классу с их единственным экземпляром, созданным только первым. Нестатические переменные инициализируются каждый раз, когда вы создаете объект класса.

Теперь, переходя к вашему вопросу, когда вы используете оператор new (), мы будем создавать копию каждого нестатического поля для каждого объекта, но это не относится к статическим полям. Вот почему он дает ошибку времени компиляции, если вы ссылаетесь на статическую переменную из нестатического метода.

Кришна
источник
0

Этот вопрос не нов, и существующие ответы дают хорошую теоретическую основу. Я просто хочу добавить более прагматичный ответ.

getText - это метод абстрактного класса Context, и для его вызова нужен экземпляр его подкласса (Activity, Service, Application или другой). Проблема в том, что общедоступные статические конечные переменные инициализируются до создания любого экземпляра Context.

Есть несколько способов решить эту проблему:

  1. Сделайте переменную переменной-членом (полем) Activity или другого подкласса Context, удалив модификатор static и поместив его в тело класса;
  2. Сохраните его статическим и отложите инициализацию до более поздней стадии (например, в методе onCreate);
  3. Вместо фактического использования сделайте его локальной переменной.
dev.bmax
источник