Apa yang dimaksud dengan kesalahan "Tidak dapat menemukan simbol" atau "Tidak dapat menyelesaikan simbol"?

Sep 07 2014

Harap jelaskan hal berikut tentang kesalahan "Tidak dapat menemukan simbol", "Tidak dapat menyelesaikan simbol", atau "Simbol tidak ditemukan":

  • Apa yang mereka maksud?
  • Hal apa yang bisa menyebabkan mereka?
  • Bagaimana cara programmer memperbaikinya?

Pertanyaan ini dirancang untuk memasukkan T&J yang komprehensif tentang kesalahan kompilasi umum ini di Java.

Jawaban

441 StephenC Sep 07 2014 at 08:12

0. Apakah ada perbedaan antara kedua kesalahan tersebut?

Tidak juga. "Tidak dapat menemukan simbol", "Tidak dapat menyelesaikan simbol" dan "Simbol tidak ditemukan" semuanya memiliki arti yang sama. Kompiler Java yang berbeda menggunakan fraseologi yang berbeda.

1. Apa yang dimaksud dengan 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.

Kesalahan "Tidak dapat menemukan simbol" adalah tentang pengenal. Ketika kode Anda dikompilasi, kompilator perlu mencari tahu apa arti setiap pengenal dalam kode Anda.

Kesalahan "Tidak dapat menemukan simbol" berarti kompilator tidak dapat melakukan ini. Kode Anda tampaknya mengacu pada sesuatu yang tidak dipahami oleh kompilator.

2. Apa yang dapat menyebabkan kesalahan "Tidak dapat menemukan simbol"?

Sebagai urutan pertama, hanya ada satu penyebab. Kompilator mencari di semua tempat di mana pengenal harus didefinisikan, dan tidak dapat menemukan definisinya. Ini bisa disebabkan oleh beberapa hal. Yang umum adalah sebagai berikut:

  • Untuk pengenal secara umum:

    • Mungkin Anda salah mengeja nama; yaitu, StringBiulderbukan StringBuilder. Java tidak dapat dan tidak akan mencoba untuk mengkompensasi kesalahan ejaan atau pengetikan yang buruk.
    • Mungkin kasus Anda salah; yaitu, stringBuilderbukan StringBuilder. Semua pengenal 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, Anda akan sangat terlindungi dari kesalahan ini ...)
    • Mungkin Anda mencoba menggunakan sesuatu yang dideklarasikan "di tempat lain"; yaitu dalam konteks yang berbeda di mana Anda secara implisit memberi tahu kompilator untuk melihatnya. (Kelas yang berbeda? Ruang lingkup yang berbeda? Paket yang berbeda? Basis kode yang berbeda?)
  • Untuk pengenal yang harus mengacu pada variabel:

    • Mungkin Anda lupa mendeklarasikan variabel.
    • Mungkin deklarasi variabel berada di luar ruang lingkup pada titik Anda mencoba menggunakannya. (Lihat contoh di bawah)
  • Untuk pengidentifikasi yang harus berupa nama metode atau bidang:

    • Mungkin Anda mencoba merujuk ke metode atau bidang yang diwariskan yang tidak dideklarasikan di kelas atau antarmuka induk / leluhur.

    • Mungkin Anda mencoba merujuk ke metode atau bidang yang tidak ada (yaitu belum dideklarasikan) dalam tipe yang Anda gunakan; misalnya "someString".push()2 .

    • Mungkin Anda mencoba menggunakan metode sebagai bidang, atau sebaliknya; misalnya "someString".lengthatau someArray.length().

    • Mungkin Anda salah mengoperasikan array daripada elemen array; misalnya

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // maybe that should be 'strings[0].charAt(3)'
      
  • Untuk pengenal yang harus berupa nama kelas:

    • Mungkin Anda lupa mengimpor kelas.

    • Mungkin Anda menggunakan impor "bintang", tetapi kelasnya tidak ditentukan dalam paket mana pun yang Anda impor.

    • Mungkin Anda lupa newseperti:

          String s = String();  // should be 'new String()'
      
  • Untuk kasus di mana jenis atau instance tampaknya tidak memiliki anggota yang Anda harapkan:

    • Mungkin Anda telah mendeklarasikan kelas bersarang atau parameter umum yang membayangi tipe yang ingin Anda gunakan.
    • Mungkin Anda membayangi variabel statis atau instance.
    • Mungkin Anda mengimpor jenis yang salah; misalnya karena penyelesaian IDE atau koreksi otomatis.
    • Mungkin Anda menggunakan (mengompilasi) versi API yang salah.
    • Mungkin Anda lupa mentransmisikan objek Anda ke subkelas yang sesuai.

Masalahnya seringkali merupakan kombinasi dari hal-hal di atas. Misalnya, mungkin Anda "membintangi" mengimpor java.io.*dan kemudian mencoba menggunakan Fileskelas ... yang ada di java.niobukan java.io. Atau mungkin Anda bermaksud untuk menulis File... yang merupakan salah satu kelas java.io.


Berikut ini contoh bagaimana cakupan 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 kita sebelumnya menyatakan i, bahwa deklarasi hanya dalam lingkup untuk forpernyataan dan tubuhnya. Referensi ke idalam ifpernyataan tidak dapat melihat deklarasi tersebut i. Itu di luar ruang lingkup .

(Koreksi yang sesuai di sini mungkin untuk memindahkan ifpernyataan di dalam loop, atau mendeklarasikan isebelum dimulainya loop.)


Berikut adalah contoh yang menyebabkan kebingungan ketika salah ketik mengarah ke kesalahan "Tidak dapat menemukan simbol" yang tampaknya tidak dapat dijelaskan:

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. Tapi (Saya mendengar Anda berkata) Saya menyatakannya!

Masalahnya adalah titik koma licik ( ;) sebelum {. Sintaks bahasa Java mendefinisikan titik koma dalam konteks itu sebagai 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);

Terlepas dari pernyataan sebelumnya, ekspresi tmpdalam tmp(...)ekspresi salah. Kompilator akan mencari metode yang dipanggil tmp, dan tidak akan menemukannya. Yang dideklarasikan sebelumnya tmpada di namespace untuk variabel, bukan namespace untuk metode.

Dalam contoh yang saya temukan, pemrogram sebenarnya telah meninggalkan operator. Yang ingin dia tulis adalah ini:

int res = tmp * (a + b);

Ada alasan lain mengapa kompilator mungkin tidak menemukan simbol jika Anda mengkompilasi dari baris perintah. Anda mungkin lupa untuk mengkompilasi atau mengkompilasi ulang beberapa kelas lain. Misalnya, jika Anda memiliki kelas Foodan Bartempat Foopenggunaan Bar. Jika Anda belum pernah mengkompilasi Bardan menjalankannya javac Foo.java, Anda mungkin akan menemukan bahwa kompilator tidak dapat menemukan simbolnya Bar. Jawaban sederhananya adalah dengan mengumpulkan Foodan Barbersama; misalnya javac Foo.java Bar.javaatau javac *.java. Atau lebih baik lagi menggunakan alat build Java; misalnya Ant, Maven, Gradle dan sebagainya.

Ada beberapa penyebab lain yang lebih tidak jelas juga ... yang akan saya bahas di bawah ini.

3. Bagaimana cara memperbaiki kesalahan ini?

Secara umum, Anda memulai dengan mencari tahu apa yang menyebabkan kesalahan kompilasi.

  • Lihat baris di file yang ditunjukkan oleh pesan kesalahan kompilasi.
  • Identifikasi simbol mana yang dibicarakan oleh pesan kesalahan tersebut.
  • Cari tahu mengapa kompilator mengatakan bahwa ia tidak dapat menemukan simbol; Lihat di atas!

Kemudian Anda berpikir tentang apa yang seharusnya dikatakan kode Anda. Kemudian akhirnya Anda menentukan koreksi apa yang perlu Anda lakukan pada kode sumber Anda untuk melakukan apa yang Anda inginkan.

Perhatikan bahwa tidak semua "koreksi" itu benar. Pertimbangkan ini:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Misalkan kompilator mengatakan "Tidak dapat menemukan simbol" untuk j. Ada banyak cara saya bisa "memperbaiki" itu:

  • Saya bisa mengubah batin formenjadi for (int j = 1; j < 10; j++)- mungkin benar.
  • Saya bisa menambahkan deklarasi j sebelumfor loop dalam , atau forloop luar - mungkin benar.
  • Saya bisa mengubah jke idalam forloop dalam - mungkin salah!
  • dan seterusnya.

Intinya adalah Anda perlu memahami apa yang coba dilakukan kode Anda untuk menemukan perbaikan yang tepat.

4. Penyebab tidak jelas

Berikut adalah beberapa kasus di mana "Tidak dapat menemukan simbol" tampaknya tidak dapat dijelaskan ... sampai Anda melihat lebih dekat.

  1. Dependensi salah : Jika Anda menggunakan IDE atau fitur build yang mengelola jalur build dan dependensi project, 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 tersebut. Jika Anda menggunakan IDE, periksa konfigurasi jalur build proyek.

  2. Anda tidak mengkompilasi ulang : Kadang-kadang terjadi bahwa programmer Java baru tidak memahami cara kerja rantai alat Java, atau belum menerapkan "proses pembangunan" yang berulang; misalnya menggunakan IDE, Ant, Maven, Gradle, dan sebagainya. Dalam situasi seperti itu, programmer bisa saja mengejar ekornya untuk mencari kesalahan ilusi yang sebenarnya disebabkan oleh tidak mengkompilasi ulang kode dengan benar, dan sejenisnya ...

  3. Masalah build sebelumnya : Ada kemungkinan bahwa build sebelumnya gagal dengan cara yang memberikan file JAR dengan class 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 hal ini, gunakan tar -tvfuntuk mendaftar isi file JAR tersangka.

  4. Masalah IDE : Orang-orang telah melaporkan kasus-kasus di mana IDE mereka menjadi bingung dan compiler di IDE tidak dapat menemukan kelas yang ada ... atau situasi sebaliknya.

  • Ini dapat 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 mungkin bug IDE. Misalnya @Joel Costigliola menjelaskan skenario di mana Eclipse tidak menangani pohon "tes" Maven dengan benar: lihat jawaban ini .

  1. Masalah Android : Saat Anda memprogram untuk Android, dan Anda memiliki kesalahan "Tidak dapat menemukan simbol" yang terkait dengannya R, ketahuilah bahwa Rsimbol ditentukan oleh context.xmlfile. Periksa apakah context.xmlfile Anda benar dan di tempat yang benar, dan bahwa Rfile kelas yang sesuai telah dibuat / dikompilasi. Perhatikan bahwa simbol Java peka huruf besar / kecil, jadi ID XML yang sesuai juga peka huruf besar / kecil.

    Kesalahan simbol lainnya pada Android kemungkinan besar disebabkan oleh alasan yang disebutkan sebelumnya; misalnya ketergantungan hilang atau salah, nama paket salah, metode atau bidang yang tidak ada dalam versi API tertentu, kesalahan ejaan / pengetikan, dan sebagainya.

  2. Mendefinisikan ulang kelas sistem : Saya telah melihat kasus di mana kompilator mengeluh bahwa substringsimbol yang tidak dikenal dalam sesuatu seperti berikut ini

    String s = ...
    String s1 = s.substring(1);
    

    Ternyata pemrogram telah membuat versi mereka sendiri Stringdan versi kelasnya tidak menentukan substringmetode.

    Pelajaran: Jangan mendefinisikan kelas Anda sendiri dengan nama yang sama dengan kelas perpustakaan umum!

  3. Homoglyphs: Jika Anda menggunakan encoding UTF-8 untuk file sumber Anda, mungkin saja memiliki pengenal yang terlihat sama, tetapi sebenarnya berbeda karena mengandung homoglyph. Lihat halaman ini untuk informasi lebih lanjut.

    Anda dapat menghindari ini dengan membatasi diri Anda pada ASCII atau Latin-1 sebagai pengkodean file sumber, dan menggunakan \uxxxxpelolosan Java 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 ke atas bukit, papan lebih kuat pada sisinya, dan Anda tidak dapat mendorong tali .

26 thinkterry Apr 17 2015 at 15:50

Anda juga akan mendapatkan kesalahan ini jika lupa new:

String s = String();

melawan

String s = new String();

karena panggilan tanpa newkata kunci akan mencoba dan mencari metode (lokal) yang dipanggil Stringtanpa argumen - dan tanda tangan metode tersebut kemungkinan besar tidak ditentukan.

14 Jan Dec 06 2015 at 16:19

Satu lagi contoh 'Variabel di luar ruang lingkup'

Seperti yang telah saya lihat pertanyaan semacam itu beberapa kali, mungkin satu contoh lagi tentang apa yang ilegal meskipun mungkin terasa oke.

Pertimbangkan kode ini:

if(somethingIsTrue()) {
  String message = "Everything is fine";
} else {
  String message = "We have an error";
}
System.out.println(message);

Itu kode yang tidak valid. Karena tak satu pun dari variabel bernama messageterlihat di luar cakupan masing-masing - yang akan menjadi tanda kurung {}di sekitarnya dalam kasus ini.

Anda mungkin mengatakan: "Tetapi variabel bernama pesan didefinisikan dengan cara baik - sehingga pesan yang didefinisikan setelah if".

Tapi Anda salah.

Java tidak memiliki operator free()atau delete, sehingga harus bergantung pada cakupan variabel pelacakan untuk mengetahui kapan variabel tidak lagi digunakan (bersama dengan referensi ke variabel penyebab ini).

Ini sangat buruk jika Anda pikir Anda melakukan sesuatu yang baik. Saya telah melihat jenis kesalahan ini setelah "mengoptimalkan" kode seperti ini:

if(somethingIsTrue()) {
  String message = "Everything is fine";
  System.out.println(message);
} else {
  String message = "We have an error";
  System.out.println(message);
}

"Oh, ada kode duplikat, mari kita tarik keluar baris yang umum itu" -> dan begitulah.

Cara paling umum untuk menangani masalah ruang lingkup semacam ini adalah dengan menetapkan nilai lain ke nama variabel di lingkup luar dan kemudian menetapkan kembali jika:

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);
10 JoelCostigliola May 13 2016 at 17:09

Salah satu cara untuk mendapatkan kesalahan ini di Eclipse:

  1. Tentukan kelas Adi src/test/java.
  2. Tentukan kelas lain Bdi kelas src/main/javayang menggunakan itu A.

Hasil: Eclipse akan mengkompilasi kode, tetapi maven akan memberikan "Tidak dapat menemukan simbol".

Penyebab mendasar: Gerhana menggunakan jalur build gabungan untuk pohon utama dan pohon uji. Sayangnya, ini tidak mendukung penggunaan jalur build yang berbeda untuk bagian berbeda dari proyek Eclipse, yang dibutuhkan Maven.

Solusi:

  1. Jangan mendefinisikan dependensi Anda seperti itu; yaitu jangan membuat kesalahan ini.
  2. Buat basis kode Anda secara teratur menggunakan Maven sehingga Anda melihat kesalahan ini lebih awal. Salah satu cara untuk melakukannya adalah dengan menggunakan server CI.
5 GT_hash Jun 30 2018 at 18:09

"Tidak dapat menemukan" artinya, compiler yang tidak dapat menemukan variabel yang sesuai, metode, kelas dll ... jika Anda mendapat pesan kesalahan itu, pertama-tama Anda ingin mencari baris kode di mana mendapatkan pijat 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 dapat digunakan untuk nanti membutuhkan ... Perhatikan contoh berikut.

Saya akan membuat kelas demo dan mencetak nama ...

class demo{ 
      public static void main(String a[]){
             System.out.print(name);
      }
}

Sekarang lihat hasilnya ..

Kesalahan itu mengatakan, "nama variabel tidak dapat menemukan" .. Mendefinisikan dan menginisialisasi nilai untuk variabel 'nama' dapat menghapus kesalahan itu .. Sebenarnya seperti ini,

class demo{ 
      public static void main(String a[]){

             String name="smith";

             System.out.print(name);
      }
}

Sekarang lihat keluaran baru ...

Ok Berhasil memecahkan kesalahan itu .. Pada saat yang sama, jika Anda bisa mendapatkan sesuatu "tidak dapat menemukan metode" atau "tidak dapat menemukan kelas", Pertama-tama, tentukan kelas atau metode dan setelah menggunakannya ..

3 JonathanLin Mar 08 2016 at 12:58

Jika Anda mendapatkan kesalahan ini di build di tempat lain, sementara IDE Anda mengatakan semuanya baik-baik saja, 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 di versi Java yang lebih lama akan menyebabkan kesalahan ini.

3 Ajay Oct 10 2019 at 19:07

TERPECAHKAN

Menggunakan IntelliJ

Pilih Build -> Rebuild Project akan menyelesaikannya

2 DivyaJose Sep 28 2016 at 21:59

Saya juga mendapatkan kesalahan ini. (yang saya cari di Google dan saya diarahkan ke halaman ini)

Masalah: Saya memanggil metode statis yang ditentukan di kelas proyek A dari kelas yang ditentukan di proyek lain B. Saya mendapatkan kesalahan berikut:

error: cannot find symbol

Solusi: Saya menyelesaikan ini dengan terlebih dahulu membangun proyek tempat metode ditentukan, lalu proyek tempat metode itu dipanggil.

2 UdayKiranPulipati Jan 24 2019 at 18:18

Jika path build Java eclipse dipetakan ke 7, 8 dan di Project pom.xml properti Maven java.version disebutkan versi Java yang lebih tinggi (9,10,11, dll ..,) daripada 7,8, Anda perlu memperbarui di pom. file xml.

Di Eclipse jika Java dipetakan ke Java versi 11 dan di pom.xml itu dipetakan ke Java versi 8. Perbarui dukungan Eclipse ke Java 11 dengan melalui langkah-langkah di bawah ini di Bantuan IDE eclipse -> Instal Perangkat Lunak Baru ->

Tempel tautan berikut http://download.eclipse.org/eclipse/updates/4.9-P-builds di Work With

atau

Tambahkan (Jendela Popup akan terbuka) ->

Name:Dukungan Java 11 Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

kemudian perbarui versi Java di properti Maven dari file pom.xml seperti di bawah ini

<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

Terakhir lakukan klik kanan pada project Debug as -> Maven clean, langkah build Maven

1 avp Aug 18 2018 at 08:45

Ada berbagai skenario seperti yang disebutkan orang di atas. Beberapa hal yang telah membantu saya menyelesaikan masalah ini.

  1. Jika Anda menggunakan IntelliJ

    File -> 'Invalidate Caches/Restart'

ATAU

  1. Kelas yang direferensikan berada di proyek lain dan ketergantungan itu tidak ditambahkan ke file build Gradle dari proyek saya. Jadi saya menambahkan ketergantungan menggunakan

    compile project(':anotherProject')

dan itu berhasil. HTH!

1 ANILKUMAR Aug 07 2019 at 11:59

Anda mengkompilasi kode Anda menggunakan kompilasi maven dan kemudian menggunakan uji maven untuk menjalankannya 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 kemudian jalankan pengujian. Bagi saya, cara itu berhasil.

1 VIPINKUMAR Sep 08 2019 at 14:50

Dalam kasus saya - saya harus melakukan operasi di bawah ini:

  1. Pindahkan context.xmlfile dari src/java/packageke resourcedirektori (IntelliJ IDE)
  2. targetDirektori bersih .
Striker Sep 06 2017 at 19:47

Sebagai petunjuk, lihat lebih dekat nama kelas yang memunculkan kesalahan dan nomor baris, contoh: Kegagalan kompilasi [ERROR] \ application \ xxxxx.java: [44,30] error: tidak dapat menemukan simbol

Satu penyebab lainnya adalah metode yang tidak didukung untuk versi java, katakan jdk7 vs 8. Periksa% JAVA_HOME% Anda

sakra Jul 20 2020 at 19:31

Kami mendapatkan kesalahan dalam proyek Java yang disiapkan sebagai build multi-proyek Gradle. Ternyata salah satu subproyek tidak memiliki plugin Gradle Java Library . Ini mencegah file kelas subproyek terlihat oleh proyek lain dalam build.

Setelah menambahkan plugin pustaka Java ke subproyek build.gradledengan cara berikut, kesalahannya hilang:

plugins {
    ...
    id 'java-library'
}
FelipeFranco Nov 20 2020 at 04:03

Saya memecahkan kesalahan ini seperti ini ... Kegilaan android. Saya memiliki nama paket sebagai Adaptor dan saya mengubah nama menjadi adaptor dengan "a" dan bukan "A" dan memecahkan kesalahan.