Неможливо зробити статичну посилання на нестатичний метод


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();

Щоб викликати метод екземпляра, ви викликаєте його в instanc ( myObject):

myObject.getText(...)

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

... = SomeClass.final

І вони не можуть працювати разом, оскільки вони працюють в різних просторах даних (дані екземпляра та дані класу)

Дозвольте спробувати і пояснити. Розглянемо цей клас (psuedocode):

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()вимагають від нього нестатичності?


він статичний, тому що я називаю його з декількох файлів у своєму проекті. коли я видалив "статичний", код помилки зник, але тепер у мене є багато помилок в інших файлах, які використовують цю змінну.
Чень М

Але це моя суть. Вам потрібно зрозуміти, коли їх можна використовувати.
Преет Сангха

коли я додаю рядок "Constants notifications_values ​​= new Constannts (); до мого основного класу активності він компілюється ОК, але в емуляторі він виходить з ладу, коли ця діяльність запущена
Chen M

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поля.


1
велике дякую, я змінив усі файли відповідно до вашої рекомендації.
Чень М

Я намагався це зробити, але для масиву рядків і з String a[] = context.getTextArray(R.array.myStringArray); ; він, однак, дає мені помилку The method getTextArray(int) is undefined for the type Context- чому це було б не визначено, тоді як він працює з getText?
сприятливий99

1
@ auspicious99 просто тому Context, що у методу не називається getTextArray, але є getText. Можливо, ви думаєте про те, Resourcesщо маєтеgetTextArray
dave.c

Ах, дякую! Пройшов у ресурсах замість контексту (від активності до неактивності), і мій getStringArray працював.
сприятливий99

9

для інших, які знаходять це в пошуку:

Я часто отримую цю, коли випадково викликаю функцію, використовуючи назву класу, а не ім'я об'єкта. Зазвичай це відбувається, тому що я даю їм занадто схожі назви: P

тобто:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Це, очевидно, статичний метод. (добре для чогось) Але те, що я дуже хотів зробити (у більшості випадків)

myclass.someFunction();

Це така нерозумна помилка, але кожні пару місяців я витрачаю близько 30 хвилин, що возиться з vars у визначеннях "MyClass", щоб розібратися, що я роблю неправильно, коли насправді, це просто помилка.

Смішна примітка: переповнення стека підкреслює синтаксис, щоб помилка дійсно стала очевидною.


Чи ваш IDE також не підкреслює це? Я думаю, ви можете налаштувати це так:
Маттіас Мейд

2

Ви можете зробити свою змінну нестатичною

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

або зробити метод "getText" статичним (якщо це взагалі можливо)


2

getText є членом вашої активності, тому його потрібно викликати, коли "це" існує. Ваша статична змінна ініціалізується під час завантаження класу до створення вашої активності.

Оскільки ви хочете, щоб змінна була ініціалізована з рядка Resource, вона не може бути статичною. Якщо ви хочете, щоб він був статичним, ви можете ініціалізувати його зі значенням String.


2

Не можна посилатися на статичну змінну з нестатичним методом. Щоб зрозуміти це, потрібно зрозуміти різницю між статичним і нестатичним.

Статичні змінні - змінні класу, вони належать до класу лише з одним екземпляром, створеним лише на першому. Нестатичні змінні ініціалізуються щоразу, коли ви створюєте об’єкт класу.

Тепер до вашого питання, коли ви використовуєте оператора new (), ми створимо копію всіх нестатичних файлів, поданих для кожного об'єкта, але це не стосується статичних полів. Ось чому він дає помилку часу компіляції, якщо ви посилаєтесь на статичну змінну від нестатичного методу.


0

Це питання не є новим, і відповіді, що існують, дають хорошу теоретичну основу. Я просто хочу додати більш прагматичну відповідь.

getText - це метод абстрактного класу контексту, і для його виклику потрібен екземпляр його підкласу (Діяльність, Сервіс, Приклад чи інше). Проблема полягає в тому, що загальнодоступні статичні кінцеві змінні ініціалізуються перед створенням будь-якого примірника контексту.

Існує кілька способів вирішити це:

  1. Зробіть змінну членом змінною (полем) діяльності або іншим підкласом контексту, видаливши статичний модифікатор і помістивши його в тіло класу;
  2. Тримати його статичним і затримати ініціалізацію до більш пізньої точки (наприклад, у методі onCreate);
  3. Зробіть це локальною змінною за місцем фактичного використання.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.