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
42
dan '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
StringBiulder
bukannya StringBuilder
. Java tidak dapat dan tidak akan mencoba mengkompensasi kesalahan pengejaan atau pengetikan yang buruk.
- Mungkin Anda salah kasus; yaitu
stringBuilder
bukannya StringBuilder
. Semua pengidentifikasi Java peka huruf besar-kecil.
- Mungkin Anda menggunakan garis bawah secara tidak tepat; yaitu
mystring
dan my_string
berbeda. (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 Files
kelas ... yang java.nio
tidak 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 i
dalam if
pernyataan. Meskipun kami sebelumnya menyatakan i
, deklarasi itu hanya dalam ruang lingkup untuk for
pernyataan dan badannya. Referensi i
dalam if
pernyataan tidak dapat melihat deklarasi itu i
. Itu di luar jangkauan .
(Koreksi yang tepat di sini mungkin untuk memindahkan if
pernyataan di dalam loop, atau untuk menyatakan i
sebelum 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 println
panggilan yang mengatakan bahwa i
tidak 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 for
loop. 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 for
lingkaran, dan oleh karena itu deklarasi sebelumnya i
dalam for
pernyataan 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, tmp
dalam tmp(...)
ungkapan itu keliru. Kompiler akan mencari metode yang disebut tmp
, dan tidak akan menemukannya. Yang dideklarasikan sebelumnya tmp
adalah 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 Foo
dan di Bar
mana Foo
menggunakan Bar
. Jika Anda belum pernah mengkompilasi Bar
dan menjalankan javac Foo.java
, Anda dapat menemukan bahwa kompiler tidak dapat menemukan simbol Bar
. Jawaban sederhananya adalah mengkompilasi Foo
dan Bar
bersama - sama; misalnya javac Foo.java Bar.java
atau 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
for
untuk for (int j = 1; j < 10; j++)
- mungkin benar.
- Saya bisa menambahkan deklarasi untuk
j
sebelumfor
loop dalam , atau for
loop luar - mungkin benar.
- Saya dapat mengubah
j
ke i
dalam for
lingkaran 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 -tvf
untuk 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 R
simbol ditentukan oleh context.xml
file. Periksa apakah context.xml
file Anda benar dan di tempat yang benar, dan bahwa R
file 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 substring
adalah simbol yang tidak dikenal dalam sesuatu seperti berikut ini
String s = ...
String s1 = s.substring(1);
Ternyata programmer telah membuat versinya sendiri String
dan versinya tentang kelas tidak mendefinisikan substring
metode.
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 \uxxxx
escapes 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 .
println
diSystem.out.println
jika ditempatkan di tingkat kelas bawah compiler standar akan memberi kita<identifier> expected
( demo ) tapi di IntelliJ kita akan melihatCannot resolve symbol 'println'
( demo ).Anda juga akan mendapatkan kesalahan ini jika Anda lupa
new
:melawan
karena panggilan tanpa
new
kata kunci akan mencoba dan mencari metode (lokal) yang dipanggilString
tanpa argumen - dan metode tanda tangan itu kemungkinan tidak ditentukan.sumber
Satu lagi contoh 'Variabel di luar ruang lingkup'
Seperti yang telah saya lihat beberapa pertanyaan semacam itu beberapa kali, mungkin satu contoh lagi untuk apa yang ilegal bahkan jika mungkin terasa baik - baik saja.
Pertimbangkan kode ini:
Itu kode yang tidak valid. Karena tak satu pun dari variabel bernama
message
terlihat di luar ruang lingkup masing-masing - yang akan menjadi tanda kurung sekitarnya{}
dalam kasus ini.Anda mungkin mengatakan: "Tetapi variabel bernama pesan didefinisikan dengan cara baik - sehingga pesan yang didefinisikan setelah
if
".Tapi kamu salah.
Java tidak memiliki
free()
ataudelete
operator, jadi ia harus bergantung pada pelacakan lingkup variabel untuk mengetahui kapan variabel tidak lagi digunakan (bersama dengan referensi ke variabel penyebab ini).Ini sangat buruk jika Anda berpikir Anda melakukan sesuatu yang baik. Saya telah melihat kesalahan semacam ini setelah "mengoptimalkan" kode seperti ini:
"Oh, ada kode duplikat, mari kita tarik garis umum keluar" -> dan di sana itu.
Cara paling umum untuk menangani jenis masalah lingkup ini adalah dengan melakukan pra-tetapkan nilai-nilai lain ke nama-nama variabel dalam lingkup luar dan kemudian ditugaskan kembali jika:
sumber
final
.Salah satu cara untuk mendapatkan kesalahan ini di Eclipse:
A
disrc/test/java
.B
di kelassrc/main/java
yang menggunakanA
.Hasil: Eclipse akan mengkompilasi kode, tetapi maven akan memberikan "Tidak dapat menemukan simbol".
Penyebab mendasar: Eclipse menggunakan jalur build gabungan untuk pohon utama dan uji. Sayangnya, itu tidak mendukung penggunaan jalur pembangunan yang berbeda untuk bagian proyek Eclipse yang berbeda, yang diperlukan oleh Maven.
Solusi:
sumber
"Tidak dapat menemukan" berarti bahwa, kompiler yang tidak dapat menemukan variabel yang sesuai, metode, kelas dll ... jika Anda mendapatkan pijatan kesalahan, pertama-tama Anda ingin menemukan baris kode di mana mendapatkan pijatan kesalahan .. Dan kemudian Anda akan dapat menemukan variabel, metode, atau kelas mana yang belum ditentukan sebelum menggunakannya. Setelah konfirmasi, inisialisasi variabel, metode, atau kelas tersebut nanti dapat digunakan ... Pertimbangkan contoh berikut.
Saya akan membuat kelas demo dan mencetak nama ...
Sekarang lihat hasilnya ..
Kesalahan itu mengatakan, "nama variabel tidak dapat menemukan" .. Menentukan dan menginisialisasi nilai untuk variabel 'nama' dapat menghapus kesalahan itu .. Sebenarnya seperti ini,
Sekarang lihat output baru ...
Ok Berhasil menyelesaikan kesalahan itu..Pada saat yang sama, jika Anda bisa mendapatkan "tidak dapat menemukan metode" atau "tidak dapat menemukan kelas" sesuatu, Pada awalnya, tentukan kelas atau metode dan setelah menggunakannya ..
sumber
Jika Anda mendapatkan kesalahan ini di build di tempat lain, sementara IDE Anda mengatakan semuanya baik-baik saja, maka periksa apakah Anda menggunakan versi Java yang sama di kedua tempat.
Misalnya, Java 7 dan Java 8 memiliki API yang berbeda, jadi memanggil API yang tidak ada dalam versi Java yang lebih lama akan menyebabkan kesalahan ini.
sumber
Saya juga mendapatkan kesalahan ini. (yang saya cari Google dan saya diarahkan ke halaman ini)
Masalah: Saya memanggil metode statis yang didefinisikan dalam kelas proyek A dari kelas yang ditentukan dalam proyek lain B. Saya mendapatkan kesalahan berikut:
Solusi: Saya menyelesaikan ini dengan terlebih dahulu membangun proyek tempat metode didefinisikan kemudian proyek tempat metode itu dipanggil.
sumber
Jika eclipse Java build path dipetakan ke 7, 8 dan di Project pom.xml properti Maven java.version disebutkan versi Java yang lebih tinggi (9,10,11, dll.,) Dari 7,8 Anda perlu memperbarui di pom. file xml.
Dalam Eclipse jika Java dipetakan ke Java versi 11 dan di pom.xml dipetakan ke Java versi 8. Perbarui dukungan Eclipse ke Java 11 dengan melalui langkah-langkah di bawah ini di eclipse IDE Help -> Install New Software ->
Tempel tautan berikut http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With
atau
Tambah (Jendela sembulan akan terbuka) ->
Name:
Java 11 mendukungLocation:
http://download.eclipse.org/eclipse/updates/4.9-P-buildskemudian perbarui versi Java di properti Maven file pom.xml seperti di bawah ini
Akhirnya lakukan klik kanan pada proyek Debug sebagai -> Maven bersih, langkah membangun Maven
sumber
TERPECAHKAN
Pilih Build -> Rebuild Project akan menyelesaikannya
sumber
Mungkin ada berbagai skenario seperti yang disebutkan orang di atas. Beberapa hal yang telah membantu saya menyelesaikan ini.
Jika Anda menggunakan IntelliJ
File -> 'Invalidate Caches/Restart'
ATAU
Kelas yang dirujuk ada di proyek lain dan ketergantungan itu tidak ditambahkan ke file build Gradle proyek saya. Jadi saya menambahkan ketergantungan menggunakan
compile project(':anotherProject')
dan itu berhasil. HTH!
sumber
Anda mengkompilasi kode Anda menggunakan maven mengkompilasi dan kemudian menggunakan uji maven untuk menjalankannya bekerja dengan baik. Sekarang jika Anda mengubah sesuatu dalam kode Anda dan kemudian tanpa kompilasi Anda menjalankannya, Anda akan mendapatkan kesalahan ini.
Solusi: Sekali lagi kompilasi dan jalankan uji. Bagi saya itu bekerja dengan cara ini.
sumber
Dalam kasus saya - saya harus melakukan operasi di bawah ini:
context.xml
file darisrc/java/package
keresource
direktori (IntelliJ IDE)target
direktori.sumber
Untuk petunjuk, lihat lebih dekat pada nama kelas yang melempar kesalahan dan nomor baris, contoh: Kegagalan kompilasi [ERROR] \ application \ xxxxx.java: [44,30] galat: tidak dapat menemukan simbol
Salah satu penyebab lainnya adalah metode yang tidak didukung untuk versi java katakanlah jdk7 vs 8. Periksa% JAVA_HOME Anda
sumber