0. Apakah ada perbedaan antara kedua kesalahan?
Tidak juga. "Tidak dapat menemukan simbol" dan "Tidak dapat menyelesaikan simbol" memiliki arti yang sama. Beberapa kompiler Java menggunakan satu frase, dan beberapa yang lain.
1. Apa artinya kesalahan "Tidak dapat menemukan simbol"?
Pertama, ini adalah kesalahan kompilasi 1 . Ini berarti bahwa baik ada masalah dalam kode sumber Java Anda, atau ada masalah dalam cara yang Anda mengkompilasinya.
Kode sumber Java Anda terdiri dari hal-hal berikut:
- Kata kunci: seperti
true, false, class, while, dan sebagainya.
- Literal: suka
42dan 'X'dan "Hi mum!".
- Operator dan token non-alfanumerik lain: seperti
+, =, {, dan sebagainya.
- Pengidentifikasi: seperti
Reader, i, toString, processEquibalancedElephants, dan sebagainya.
- Komentar dan spasi putih.
Kesalahan "Tidak dapat menemukan simbol" adalah tentang pengidentifikasi. Ketika kode Anda dikompilasi, kompiler perlu mengetahui apa arti setiap pengidentifikasi dalam kode Anda.
Kesalahan "Tidak dapat menemukan simbol" berarti bahwa kompiler tidak dapat melakukan ini. Kode Anda tampaknya merujuk pada sesuatu yang tidak dimengerti oleh kompiler.
2. Apa yang dapat menyebabkan kesalahan "Tidak dapat menemukan simbol"?
Sebagai urutan pertama, hanya ada satu penyebab. Kompiler mencari di semua tempat di mana pengidentifikasi harus didefinisikan, dan tidak dapat menemukan definisi. Ini bisa disebabkan oleh beberapa hal. Yang umum adalah sebagai berikut:
- Untuk pengidentifikasi secara umum:
- Mungkin Anda salah mengeja namanya; yaitu
StringBiulderbukannya StringBuilder. Java tidak dapat dan tidak akan mencoba mengkompensasi kesalahan pengejaan atau pengetikan yang buruk.
- Mungkin Anda salah kasus; yaitu
stringBuilderbukannya StringBuilder. Semua pengidentifikasi Java peka huruf besar-kecil.
- Mungkin Anda menggunakan garis bawah secara tidak tepat; yaitu
mystringdan my_stringberbeda. (Jika Anda tetap berpegang pada aturan gaya Java, sebagian besar Anda akan terlindungi dari kesalahan ini ...)
- Mungkin Anda mencoba menggunakan sesuatu yang dinyatakan "di tempat lain"; yaitu dalam konteks yang berbeda ke tempat Anda secara implisit mengatakan kepada kompiler untuk melihat. (Kelas yang berbeda? Ruang lingkup yang berbeda? Paket yang berbeda? Pangkalan kode yang berbeda?)
- Untuk pengidentifikasi yang harus merujuk ke variabel:
- Mungkin Anda lupa mendeklarasikan variabel.
- Mungkin deklarasi variabel berada di luar cakupan pada titik Anda mencoba menggunakannya. (Lihat contoh di bawah)
Untuk pengidentifikasi yang harus berupa metode atau nama bidang:
Untuk pengidentifikasi yang harus berupa nama kelas:
Untuk kasus di mana jenis atau instance tampaknya tidak memiliki anggota yang Anda harapkan memiliki:
- Mungkin Anda telah mendeklarasikan kelas bersarang atau parameter umum yang membayangi tipe yang ingin Anda gunakan.
- Mungkin Anda membayangi variabel statis atau instan.
- Mungkin Anda mengimpor jenis yang salah; misalnya karena penyelesaian IDE atau koreksi otomatis.
- Mungkin Anda menggunakan (kompilasi melawan) versi API yang salah.
- Mungkin Anda lupa melemparkan objek ke subkelas yang sesuai.
Masalahnya sering merupakan kombinasi dari yang di atas. Sebagai contoh, mungkin Anda "membintangi" diimpor java.io.*dan kemudian mencoba menggunakan Fileskelas ... yang java.niotidak java.io. Atau mungkin Anda bermaksud menulis File... yang merupakan kelas di java.io.
Berikut adalah contoh bagaimana pelingkupan variabel yang salah dapat menyebabkan kesalahan "Tidak dapat menemukan simbol":
List<String> strings = ...
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase("fnord")) {
break;
}
}
if (i < strings.size()) {
...
}
Ini akan memberikan kesalahan "Tidak dapat menemukan simbol" untuk idalam ifpernyataan. Meskipun kami sebelumnya menyatakan i, deklarasi itu hanya dalam ruang lingkup untuk forpernyataan dan badannya. Referensi idalam ifpernyataan tidak dapat melihat deklarasi itu i. Itu di luar jangkauan .
(Koreksi yang tepat di sini mungkin untuk memindahkan ifpernyataan di dalam loop, atau untuk menyatakan isebelum dimulainya loop.)
Berikut adalah contoh yang menyebabkan kebingungan di mana kesalahan ketik menyebabkan kesalahan yang tampaknya tidak dapat dijelaskan: "Tidak dapat menemukan simbol":
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
Ini akan memberi Anda kesalahan kompilasi dalam printlnpanggilan yang mengatakan bahwa itidak dapat ditemukan. Tetapi (saya mendengar Anda berkata) saya menyatakannya!
Masalahnya adalah titik koma licik ( ;) sebelum {. Sintaks bahasa Java mendefinisikan titik koma dalam konteks itu menjadi pernyataan kosong . Pernyataan kosong kemudian menjadi badan forloop. Jadi kode itu sebenarnya berarti ini:
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!!
{
System.out.println("i is " + i);
}
The { ... }blok TIDAK tubuh forlingkaran, dan oleh karena itu deklarasi sebelumnya idalam forpernyataan keluar dari ruang lingkup di blok tersebut.
Berikut adalah contoh lain dari kesalahan "Tidak dapat menemukan simbol" yang disebabkan oleh kesalahan ketik.
int tmp = ...
int res = tmp(a + b);
Meskipun deklarasi sebelumnya, tmpdalam tmp(...)ungkapan itu keliru. Kompiler akan mencari metode yang disebut tmp, dan tidak akan menemukannya. Yang dideklarasikan sebelumnya tmpadalah dalam namespace untuk variabel, bukan namespace untuk metode.
Dalam contoh yang saya temui, programmer sebenarnya telah meninggalkan operator. Apa yang ingin ia tulis adalah ini:
int res = tmp * (a + b);
Ada alasan lain mengapa kompiler mungkin tidak menemukan simbol jika Anda mengkompilasi dari baris perintah. Anda mungkin lupa kompilasi atau kompilasi ulang beberapa kelas lain. Misalnya, jika Anda memiliki kelas Foodan di Barmana Foomenggunakan Bar. Jika Anda belum pernah mengkompilasi Bardan menjalankan javac Foo.java, Anda dapat menemukan bahwa kompiler tidak dapat menemukan simbol Bar. Jawaban sederhananya adalah mengkompilasi Foodan Barbersama - sama; misalnya javac Foo.java Bar.javaatau javac *.java. Atau lebih baik lagi menggunakan alat Java build; misal Ant, Maven, Gradle dan sebagainya.
Ada beberapa penyebab lain yang lebih tidak jelas ... yang akan saya bahas di bawah ini.
3. Bagaimana cara memperbaiki kesalahan ini?
Secara umum, Anda mulai dengan mencari tahu apa yang menyebabkan kesalahan kompilasi.
- Lihatlah baris dalam file yang ditunjukkan oleh pesan kesalahan kompilasi.
- Identifikasi simbol mana yang dibicarakan oleh pesan kesalahan.
- Cari tahu mengapa kompiler mengatakan bahwa ia tidak dapat menemukan simbol; Lihat di atas!
Kemudian Anda berpikir tentang apa yang seharusnya dikatakan oleh kode Anda. Lalu akhirnya Anda mencari koreksi apa yang perlu Anda lakukan untuk kode sumber Anda untuk melakukan apa yang Anda inginkan.
Perhatikan bahwa tidak setiap "koreksi" benar. Pertimbangkan ini:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
Misalkan kompiler mengatakan "Tidak dapat menemukan simbol" untuk j. Ada banyak cara saya bisa "memperbaiki" itu:
- Aku bisa mengubah batin
foruntuk for (int j = 1; j < 10; j++)- mungkin benar.
- Saya bisa menambahkan deklarasi untuk
j sebelumfor loop dalam , atau forloop luar - mungkin benar.
- Saya dapat mengubah
jke idalam forlingkaran dalam - mungkin salah!
- dan seterusnya.
Intinya adalah bahwa Anda perlu memahami apa yang kode Anda coba lakukan untuk menemukan perbaikan yang tepat.
4. Penyebab yang tidak jelas
Berikut adalah beberapa kasus di mana "Tidak dapat menemukan simbol" tampaknya tidak dapat dijelaskan ... sampai Anda melihat lebih dekat.
Ketergantungan yang salah : Jika Anda menggunakan IDE atau alat build yang mengelola path build dan dependensi proyek, Anda mungkin telah membuat kesalahan dengan dependensi; mis. meninggalkan ketergantungan, atau memilih versi yang salah. Jika Anda menggunakan alat build (Ant, Maven, Gradle, dll), periksa file build proyek. Jika Anda menggunakan IDE, periksa konfigurasi path build proyek.
Anda tidak mengkompilasi ulang : Terkadang terjadi bahwa programmer Java yang baru tidak memahami bagaimana rantai alat Java bekerja, atau belum menerapkan "proses pembangunan" yang berulang; misal menggunakan IDE, Ant, Maven, Gradle dan sebagainya. Dalam situasi seperti itu, programmer dapat akhirnya mengejar ekornya mencari kesalahan ilusi yang sebenarnya disebabkan oleh tidak mengkompilasi ulang kode dengan benar, dan sejenisnya ...
Masalah build sebelumnya : Ada kemungkinan bahwa build sebelumnya gagal dengan cara yang memberikan file JAR dengan kelas yang hilang. Kegagalan seperti itu biasanya akan diperhatikan jika Anda menggunakan alat build. Namun jika Anda mendapatkan file JAR dari orang lain, Anda bergantung padanya untuk membangun dengan benar, dan memperhatikan kesalahan. Jika Anda mencurigai ini, gunakan tar -tvfuntuk membuat daftar isi file JAR yang dicurigai.
Masalah IDE : Orang-orang telah melaporkan kasus di mana IDE mereka menjadi bingung dan kompiler di IDE tidak dapat menemukan kelas yang ada ... atau situasi sebaliknya.
Ini bisa terjadi jika IDE telah dikonfigurasi dengan versi JDK yang salah.
Ini bisa terjadi jika cache IDE tidak sinkron dengan sistem file. Ada cara khusus IDE untuk memperbaikinya.
Ini bisa menjadi bug IDE. Misalnya @ Joel Costigliola menjelaskan skenario di mana Eclipse tidak menangani pohon "tes" Maven dengan benar: lihat jawaban ini .
Masalah Android : Saat Anda memprogram untuk Android, dan Anda memiliki kesalahan "Tidak dapat menemukan simbol" yang terkait R, perlu diketahui bahwa Rsimbol ditentukan oleh context.xmlfile. Periksa apakah context.xmlfile Anda benar dan di tempat yang benar, dan bahwa Rfile kelas yang sesuai telah dihasilkan / dikompilasi. Perhatikan bahwa simbol Java peka terhadap huruf besar-kecil, sehingga id XML yang terkait juga peka terhadap huruf besar-kecil.
Kesalahan simbol lain pada Android kemungkinan disebabkan oleh alasan yang disebutkan sebelumnya; mis. dependensi yang hilang atau salah, nama paket salah, metode atau bidang yang tidak ada dalam versi API tertentu, kesalahan pengejaan / pengetikan, dan sebagainya.
Mendefinisikan ulang kelas sistem : Saya telah melihat kasus-kasus di mana kompiler mengeluh bahwa itu substringadalah simbol yang tidak dikenal dalam sesuatu seperti berikut ini
String s = ...
String s1 = s.substring(1);
Ternyata programmer telah membuat versinya sendiri Stringdan versinya tentang kelas tidak mendefinisikan substringmetode.
Pelajaran: Jangan mendefinisikan kelas Anda sendiri dengan nama yang sama dengan kelas perpustakaan umum!
Homoglyphs: Jika Anda menggunakan pengkodean UTF-8 untuk file sumber Anda, dimungkinkan untuk memiliki pengidentifikasi yang terlihat sama, tetapi pada kenyataannya berbeda karena mengandung homoglyphs. Lihat halaman ini untuk informasi lebih lanjut.
Anda dapat menghindari ini dengan membatasi diri Anda ke ASCII atau Latin-1 sebagai pengkodean file sumber, dan menggunakan Java \uxxxxescapes untuk karakter lain.
1 - Jika, barangkali, Anda jangan melihat ini dalam pengecualian runtime atau pesan error, maka baik Anda telah mengkonfigurasi IDE Anda untuk menjalankan kode dengan kesalahan kompilasi, atau aplikasi Anda menghasilkan dan kode kompilasi .. pada saat runtime.
2 - Tiga prinsip dasar Teknik Sipil: air tidak mengalir menanjak, papan lebih kuat di sisinya, dan Anda tidak bisa mendorong tali .