Tidak dapat membuat referensi statis ke metode non-statis

102

Membangun aplikasi multi-bahasa di Java. Mendapatkan kesalahan saat memasukkan nilai String dari R.stringfile XML sumber daya:

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

Ini adalah pesan kesalahannya:

Kesalahan: Tidak dapat membuat referensi statis ke metode non-statis getText (int) dari tipe Konteks

Bagaimana ini disebabkan dan bagaimana saya bisa mengatasinya?

Chen M
sumber
1
Mengapa Anda membutuhkannya menjadi statis untuk 'aplikasi multi bahasa'? Tidak terlalu mengerti.
xil3
3
Jangan pernah menyimpan sumber daya string dalam anggota data statis. Selalu minta melalui getString()saat Anda membutuhkannya. Dengan begitu, aplikasi Anda menyesuaikan dengan baik pengguna yang mengubah bahasa pilihan mereka.
CommonsWare

Jawaban:

143

Karena getText()non-statis Anda tidak dapat memanggilnya dari metode statis.

Untuk memahami alasannya, Anda harus memahami perbedaan di antara keduanya.

Metode contoh (non-statis) bekerja pada objek yang berjenis tertentu (kelas). Ini dibuat dengan yang baru seperti ini:

SomeClass myObject = new SomeClass();

Untuk memanggil metode instance, Anda memanggilnya di instance ( myObject):

myObject.getText(...)

Namun metode / field statis hanya dapat dipanggil pada tipe secara langsung, katakan seperti ini: Pernyataan sebelumnya tidak benar. Anda juga dapat merujuk ke bidang statis dengan referensi objek seperti myObject.staticMethod() tetapi hal ini tidak disarankan karena tidak menjelaskan bahwa mereka adalah variabel kelas.

... = SomeClass.final

Dan keduanya tidak dapat bekerja sama karena beroperasi pada ruang data yang berbeda (data contoh dan data kelas)

Biar saya coba dan jelaskan. Pertimbangkan kelas ini (psuedocode):

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

Sekarang saya memiliki kasus penggunaan berikut:

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

 Test item2 = new Test();

 Test.TTT = "1";

Apa nilainya?

Baik

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

Dengan kata lain, TTTadalah datum yang dibagikan oleh semua instance tipe. Jadi tidak masuk akal untuk mengatakannya

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

Jadi pertanyaannya adalah mengapa TTT statis atau mengapa getText () tidak statis?

Hapus staticdan itu harus melewati kesalahan ini - tetapi tanpa memahami apa jenis Anda lakukan itu hanya plester yang menempel sampai kesalahan berikutnya. Apa persyaratan getText()yang mengharuskannya menjadi non-statis?

Preet Sangha
sumber
itu statis karena saya menyebutnya dari beberapa file dalam proyek saya. ketika saya menghapus "statis" kode kesalahan hilang, tetapi sekarang saya memiliki banyak kesalahan di file lain yang menggunakan variabel ini.
Chen M
Tapi itulah maksud saya. Anda perlu memahami kapan keduanya bisa digunakan.
Preet Sangha
ketika saya menambahkan baris "Constants notifications_values ​​= new Constants (); ke kelas aktivitas utama saya, itu mengkompilasi OK tetapi di emulator itu macet ketika aktivitas ini berjalan
Chen M
12

Ada beberapa jawaban yang baik sudah dengan penjelasan mengapa campuran non-statis Contextmetode getText()tidak dapat digunakan dengan Anda static final String.

Pertanyaan yang bagus untuk ditanyakan adalah: mengapa Anda ingin melakukan ini? Anda mencoba memuat Stringdari stringssumber daya Anda , dan mengisi nilainya ke dalam public staticbidang. Saya berasumsi bahwa ini agar beberapa kelas Anda yang lain dapat mengaksesnya? Jika demikian, tidak perlu melakukan ini. Alih-alih berikan a Contextke kelas Anda yang lain dan panggil context.getText(R.string.TTT)dari dalam mereka.

public class NonActivity {

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

Dan untuk memanggil ini dari Anda Activity:

NonActivity.doStuff(this);

Ini akan memungkinkan Anda untuk mengakses Stringsumber daya Anda tanpa perlu menggunakan public staticbidang.

dave.c
sumber
1
terima kasih banyak, saya mengubah semua file sesuai dengan rekomendasi Anda.
Chen M
Saya mencoba melakukan ini, tetapi untuk string-array, dan dengan String a[] = context.getTextArray(R.array.myStringArray); ; itu, bagaimanapun, memberi saya kesalahan The method getTextArray(int) is undefined for the type Context- mengapa itu tidak terdefinisi sementara itu bekerja dengan getText?
keberuntungan99
1
@ auspicious99 hanya karena a Contexttidak memiliki metode yang dipanggil getTextArray, tetapi memiliki getText. Mungkin Anda berpikir tentang Resourcesmana yang memilikigetTextArray
dave.c
Ah terima kasih! Meneruskan Sumber Daya, bukan Konteks (dari aktivitas ke nonaktivitas), dan getStringArray saya berfungsi.
keberuntungan99
9

untuk orang lain yang menemukan ini dalam pencarian:

Saya sering mendapatkan yang ini ketika saya tidak sengaja memanggil fungsi menggunakan nama kelas daripada nama objek. Ini biasanya terjadi karena saya memberi mereka nama yang terlalu mirip: P.

yaitu:

MyClass myclass = new MyClass();

// then later

MyClass.someFunction();

Ini jelas merupakan metode statis. (baik untuk sesuatu) Tapi yang benar-benar ingin saya lakukan (dalam banyak kasus adalah)

myclass.someFunction();

Ini adalah kesalahan yang konyol, tetapi setiap beberapa bulan, saya membuang waktu sekitar 30 menit untuk mengotak-atik vars dalam definisi "MyClass" untuk mengetahui apa yang saya lakukan salah padahal sebenarnya, itu hanya salah ketik.

Catatan lucu: stack overflow menyoroti sintaks untuk membuat kesalahan sangat jelas di sini.

SpiRail
sumber
Bukankah IDE Anda juga menyoroti ini? Saya kira Anda dapat mengkonfigurasinya untuk melakukannya :)
Matthias Meid
2

Anda dapat membuat variabel Anda tidak statis

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

atau jadikan metode "getText" statis (jika memungkinkan)

Kellindil
sumber
2

getText adalah anggota Aktivitas Anda sehingga harus dipanggil jika "ini" ada. Variabel statis Anda diinisialisasi ketika kelas Anda dimuat sebelum Aktivitas Anda dibuat.

Karena Anda ingin variabel diinisialisasi dari string Sumber Daya maka itu tidak bisa statis. Jika Anda ingin menjadi statis Anda dapat menginisialisasi dengan nilai String.

Robby Pond
sumber
2

Anda tidak dapat membuat referensi ke variabel statis dari metode non-statis. Untuk memahami ini, Anda perlu memahami perbedaan antara statis dan non-statis.

Variabel statis adalah variabel kelas, mereka termasuk dalam kelas dengan satu-satunya contoh, dibuat hanya pada yang pertama. Variabel non-statis diinisialisasi setiap kali Anda membuat objek kelas.

Sekarang datang ke pertanyaan Anda, ketika Anda menggunakan operator new () kami akan membuat salinan dari setiap file non-statis untuk setiap objek, tetapi tidak untuk bidang statis. Itulah mengapa ini memberikan kesalahan waktu kompilasi jika Anda mereferensikan variabel statis dari metode non-statis.

Krishna
sumber
0

Pertanyaan ini bukanlah pertanyaan baru dan jawaban yang sudah ada memberikan beberapa latar belakang teoritis yang baik. Saya hanya ingin menambahkan jawaban yang lebih pragmatis.

getText adalah metode kelas abstrak Konteks dan untuk memanggilnya, seseorang memerlukan turunan dari subkelasnya (Aktivitas, Layanan, Aplikasi, atau lainnya). Masalahnya adalah, variabel final statis publik diinisialisasi sebelum instance Konteks dibuat.

Ada beberapa cara untuk mengatasinya:

  1. Jadikan variabel sebagai variabel anggota (bidang) Aktivitas atau subkelas Konteks lainnya dengan menghapus pengubah statis dan menempatkannya di dalam badan kelas;
  2. Jaga agar tetap statis dan tunda inisialisasi ke titik selanjutnya (mis. Dalam metode onCreate);
  3. Jadikan itu variabel lokal sebagai pengganti penggunaan sebenarnya.
dev.bmax
sumber