"Sembol bulunamıyor" veya "Sembol çözülemiyor" hatası ne anlama geliyor?
Lütfen "Sembol bulunamıyor", "Sembol çözülemiyor" veya "Sembol bulunamadı" hataları hakkında aşağıdakileri açıklayın:
- Ne demek istiyorlar?
- Onlara ne sebep olabilir?
- Programcı bunları düzeltmeye nasıl gidiyor?
Bu soru, Java'daki bu yaygın derleme hataları hakkında kapsamlı bir Soru-Cevap başlatmak için tasarlanmıştır.
Yanıtlar
0. İki hata arasında herhangi bir fark var mı?
Pek sayılmaz. "Sembol bulunamıyor", "Sembol çözülemiyor" ve "Sembol bulunamadı" hepsi aynı anlama gelir. Farklı Java derleyicileri farklı ifadeler kullanır.
1. "Sembol bulunamıyor" hatası ne anlama geliyor?
İlk olarak, bu bir derleme hatasıdır 1 . Bu demektir ya da Java kaynak kodunda bir sorun vardır, ya bunu derleme bu şekilde bir sorun vardır.
Java kaynak kodunuz aşağıdakilerden oluşur:
- Anahtar Kelimeler: gibi
true
,false
,class
,while
, vb. - Değişmezler:
42
ve'X'
ve gibi"Hi mum!"
. - Operatörler ve alfanümerik olmayan diğer belirteçleri: gibi
+
,=
,{
, vb. - Tanımlayıcıları: gibi
Reader
,i
,toString
,processEquibalancedElephants
, vb. - Yorumlar ve boşluk.
Tanımlayıcılarla ilgili bir "Sembol bulunamıyor" hatası. Kodunuz derlendiğinde, derleyicinin kodunuzdaki her bir tanımlayıcının ne anlama geldiğini hesaplaması gerekir.
"Sembol bulunamıyor" hatası, derleyicinin bunu yapamayacağı anlamına gelir. Kodunuz, derleyicinin anlamadığı bir şeye gönderme yapıyor gibi görünüyor.
2. "Sembol bulunamıyor" hatasına ne sebep olabilir?
İlk sırada, tek bir neden var. Derleyici, tanımlayıcının tanımlanması gereken tüm yerlere baktı ve tanımı bulamadı. Bunun birkaç nedeni olabilir. Yaygın olanlar aşağıdaki gibidir:
Genel olarak tanımlayıcılar için:
- Belki adı yanlış yazmışsınızdır; yani
StringBiulder
yerineStringBuilder
. Java, kötü yazım veya yazım hatalarını telafi edemez ve etmeyecektir. - Belki de davayı yanlış anladınız; yani
stringBuilder
yerineStringBuilder
. Tüm Java tanımlayıcıları büyük / küçük harfe duyarlıdır. - Belki de alt çizgileri uygunsuz bir şekilde kullandınız; yani
mystring
vemy_string
farklı. (Java stil kurallarına bağlı kalırsanız, bu hatadan büyük ölçüde korunacaksınız ...) - Belki de "başka bir yerde" ilan edilen bir şeyi kullanmaya çalışıyorsunuz; örtük olarak derleyiciye bakmasını söylediğinizden farklı bir bağlamda. (Farklı bir sınıf mı? Farklı bir kapsam mı? Farklı bir paket mi? Farklı bir kod tabanı mı?)
- Belki adı yanlış yazmışsınızdır; yani
Değişkenlere başvurması gereken tanımlayıcılar için:
- Belki de değişkeni açıklamayı unuttunuz.
- Belki de değişken bildirimi, onu kullanmaya çalıştığınız noktada kapsam dışındadır. (Aşağıdaki örneğe bakın)
Yöntem veya alan adları olması gereken tanımlayıcılar için:
Belki de üst / üst sınıflarda veya arabirimlerde bildirilmemiş, miras alınan bir yönteme veya alana başvurmaya çalışıyorsunuz.
Belki de kullandığınız türde olmayan (yani bildirilmemiş) bir yönteme veya alana başvurmaya çalışıyorsunuz; örneğin
"someString".push()
2 .Belki de bir yöntemi alan olarak kullanmaya çalışıyorsunuz ya da tam tersi; örneğin
"someString".length
veyasomeArray.length()
.Belki de yanlışlıkla dizi elemanı yerine bir dizi üzerinde çalışıyorsunuzdur; Örneğin
String strings[] = ... if (strings.charAt(3)) { ... } // maybe that should be 'strings[0].charAt(3)'
Sınıf adları olması gereken tanımlayıcılar için:
Belki de dersi almayı unuttunuz.
Belki "yıldız" içe aktarımları kullandınız, ancak sınıf, içe aktardığınız paketlerin hiçbirinde tanımlanmadı.
Belki de şu şekilde unuttunuz
new
:String s = String(); // should be 'new String()'
Tür veya örneğin, sahip olmasını beklediğiniz üyeye sahip olmadığı durumlar için:
- Belki de kullanmak istediğiniz türü gölgeleyen yuvalanmış bir sınıf veya genel bir parametre bildirmişsinizdir .
- Belki de bir statik veya örnek değişkeni gölgeliyorsunuzdur.
- Belki de yanlış türü içe aktarmışsınızdır; örneğin IDE tamamlama veya otomatik düzeltme nedeniyle.
- Belki de bir API'nin yanlış sürümünü kullanıyorsunuz (karşı derliyor).
- Belki de nesnenizi uygun bir alt sınıfa atmayı unuttunuz.
Sorun genellikle yukarıdakilerin bir kombinasyonudur. Örneğin, belki "yıldız" içe aktardınız java.io.*
ve sonra Files
içinde java.nio
olmayan ... sınıfı kullanmaya çalıştınız java.io
. Veya belki de yazmak istediniz File
... ki bu bir sınıftır java.io
.
Yanlış değişken kapsamının nasıl bir "Sembol bulunamıyor" hatasına neden olabileceğine dair bir örnek:
List<String> strings = ...
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase("fnord")) {
break;
}
}
if (i < strings.size()) {
...
}
Bu i
, if
ifadede "Sembol bulunamıyor" hatası verir . Daha önce beyan etmiş olsak da i
, bu beyan sadece ifade ve içeriği için kapsam dahilindedir for
. Yapılan atıf i
içinde if
deyimi göremiyorum bu beyanı i
. Öyle kapsam dışında .
(Burada uygun bir düzeltme, if
deyimi döngünün içine taşımak veya döngünün i
başlamasından önce bildirmek olabilir .)
Aşağıda, bir yazım hatasının görünüşte açıklanamaz bir "Sembol bulunamıyor" hatasına yol açtığı şaşkınlığa neden olan bir örnek verilmiştir:
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
Bu size println
arama i
sırasında bulunamadığını söyleyen bir derleme hatası verecektir . Ama (dediğini duydum) Ben ilan ettim!
Sorun sinsi noktalı virgül (olduğu ;
öncesi) {
. Java dili sözdizimi, bu bağlamda bir noktalı virgülü boş bir ifade olarak tanımlar . Boş ifade daha sonra for
döngünün gövdesi haline gelir . Yani bu kod aslında şu anlama geliyor:
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!!
{
System.out.println("i is " + i);
}
{ ... }
Blok gövdesi DEĞİLDİR for
döngü ve dolayısıyla önceki beyanı i
içinde for
ifadesi kapsam dışında bloğunda.
Burada, bir yazım hatasından kaynaklanan "Sembol bulunamıyor" hatasının başka bir örneği var.
int tmp = ...
int res = tmp(a + b);
Bir önceki bildiriminde rağmen tmp
içinde tmp(...)
ifade yanlıştır. Derleyici adında bir yöntem arayacak tmp
ve bulamayacaktır. Önceden bildirilen tmp
, yöntemler için ad alanı değil, değişkenler için ad alanı içindedir.
Karşılaştığım örnekte, programcı aslında bir operatörü atlamıştı. Yazmak istediği şuydu:
int res = tmp * (a + b);
Komut satırından derliyorsanız, derleyicinin bir sembol bulamamasının başka bir nedeni vardır. Başka bir sınıfı derlemeyi veya yeniden derlemeyi unutmuş olabilirsiniz. Örneğin, eğer sınıfları Foo
ve Bar
nerede Foo
kullanır Bar
. Hiç derlemediyseniz Bar
ve çalıştırırsanız javac Foo.java
, derleyicinin sembolü bulamadığını bulmakla yükümlüsünüz Bar
. Basit cevap derlemek Foo
ve Bar
birlikte yapmaktır ; örneğin javac Foo.java Bar.java
veya javac *.java
. Ya da daha iyisi bir Java oluşturma aracı kullanın; örneğin Ant, Maven, Gradle vb.
Aşağıda ele alacağım daha belirsiz başka nedenler de var.
3. Bu hataları nasıl düzeltirim?
Genel olarak, derleme hatasına neyin neden olduğunu bulmakla işe başlarsınız .
- Derleme hata mesajıyla belirtilen dosyadaki satıra bakın.
- Hata mesajının hangi sembolden bahsettiğini belirleyin.
- Anlamaya neden derleyici o sembolü bulamadığını söylüyor; yukarıyı görmek!
Sonra kodunuzun ne söylemesi gerektiğini düşünürsünüz . Sonunda, istediğinizi yapmak için kaynak kodunuzda hangi düzeltmeyi yapmanız gerektiğini çözersiniz.
Her "düzeltmenin" doğru olmadığını unutmayın. Bunu düşün:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
Derleyicinin için "Sembol bulunamıyor" dediğini varsayalım j
. Bunu "düzeltebilmemin" birçok yolu vardır:
- Ben iç değişebilir
for
Yapılırfor (int j = 1; j < 10; j++)
- Doğru muhtemelen. - İç döngüden veya dış döngüden
j
önce bir bildirim ekleyebilirim - muhtemelen doğru.for
for
- Ben değişebilir
j
içini
iç içindefor
döngü - yanlış muhtemelen! - ve bunun gibi.
Nokta olduğunu gerek kodunuzu doğru çözüm yolunu bulmak için yapmaya çalışıyor anlamak için.
4. Belirsiz nedenler
Burada "Sembol bulunamıyor" ifadesinin açıklanamaz olduğu birkaç durum var ... ta ki siz daha yakından bakana kadar.
Yanlış bağımlılıklar : Derleme yolunu ve proje bağımlılıklarını yöneten bir IDE veya derleme aracı kullanıyorsanız, bağımlılıklarla ilgili bir hata yapmış olabilirsiniz; örneğin bir bağımlılığı atlamak veya yanlış sürümü seçmek. Bir derleme aracı kullanıyorsanız (Ant, Maven, Gradle, vb.), Projenin derleme dosyasını kontrol edin. Bir IDE kullanıyorsanız, projenin derleme yolu yapılandırmasını kontrol edin.
Yeniden derlemiyorsunuz : Bazen, yeni Java programcıları Java araç zincirinin nasıl çalıştığını anlamıyor veya tekrarlanabilir bir "oluşturma süreci" uygulamamış oluyor; örneğin bir IDE, Ant, Maven, Gradle vb. kullanarak. Böyle bir durumda, programcı kuyruğunu kovalayarak, aslında kodu düzgün şekilde yeniden derlememekten kaynaklanan yanıltıcı bir hata arayabilir ve benzeri ...
Daha önceki bir yapı sorunu : Daha önceki bir yapının, eksik sınıfları olan bir JAR dosyası verecek şekilde başarısız olması mümkündür. Bir derleme aracı kullanıyorsanız, böyle bir başarısızlık genellikle fark edilir. Bununla birlikte, JAR dosyalarını başka birinden alıyorsanız, bunların düzgün bir şekilde oluşturulmasına ve hataları fark etmesine bağımlı olursunuz . Bundan şüpheleniyorsanız
tar -tvf
, şüpheli JAR dosyasının içeriğini listelemek için kullanın .IDE sorunları : İnsanlar, IDE'lerinin kafasının karıştığı ve IDE'deki derleyicinin var olan bir sınıfı bulamadığı veya tersi durumları bildirdiler.
Bu, IDE yanlış JDK sürümüyle yapılandırılmışsa olabilir.
Bu, IDE'nin önbellekleri dosya sistemiyle senkronize değilse olabilir. Bunu düzeltmenin IDE'ye özgü yolları var.
Bu bir IDE hatası olabilir. Örneğin @Joel Costigliola, Eclipse'in bir Maven "test" ağacını doğru şekilde işlemediği bir senaryoyu anlatıyor: bu yanıta bakın .
Android sorunları : Android için programlama yaparken ve ilgili "Sembol bulunamıyor" hatalarınız
R
varsa,R
sembollerincontext.xml
dosya tarafından tanımlandığını unutmayın . Senin olmadığını kontrolcontext.xml
dosyası doğru ve doğru yerde olduğunu ve karşılık gelen buR
sınıf dosyası oluşturulduktan / derlenmiş. Java sembollerinin büyük / küçük harfe duyarlı olduğunu, bu nedenle karşılık gelen XML kimliklerinin de büyük / küçük harfe duyarlı olduğunu unutmayın.Android'deki diğer sembol hataları muhtemelen daha önce bahsedilen nedenlerden kaynaklanmaktadır; örneğin eksik veya yanlış bağımlılıklar, yanlış paket adları, belirli bir API sürümünde bulunmayan yöntem veya alanlar, yazım / yazım hataları vb.
Sistem sınıflarını yeniden tanımlama : Derleyicinin
substring
aşağıdaki gibi bir şeyde bilinmeyen bir sembol olduğundan şikayet ettiği durumlar gördümString s = ... String s1 = s.substring(1);
Programcının kendi sürümünü oluşturduğu
String
ve sınıf sürümünün birsubstring
yöntem tanımlamadığı ortaya çıktı .Ders: Kendi sınıflarınızı ortak kitaplık sınıflarıyla aynı adlarla tanımlamayın!
Homoglifler: Kaynak dosyalarınız için UTF-8 kodlamasını kullanırsanız , aynı görünen , ancak homoglifler içerdikleri için aslında farklı olan tanımlayıcılara sahip olmak mümkündür . Daha fazla bilgi için bu sayfaya bakın .
Kendinizi kaynak dosya kodlaması olarak ASCII veya Latin-1 ile sınırlandırarak ve
\uxxxx
diğer karakterler için Java kaçışları kullanarak bunu önleyebilirsiniz .
1 - Eğer belki, sen mi o zaman ya sen derleme hataları ile çalışma koduna IDE yapılandırmış veya başvurunuz zamanında .. üretme ve kod derleme, bir çalışma zamanı istisnası ya da hata iletisinde görüyoruz.
2 - İnşaat Mühendisliğinin üç temel prensibi: su yokuş yukarı akmaz, tahta kenarı daha güçlüdür ve bir ipi itemezsiniz .
Ayrıca şunları unutursanız da bu hatayı alırsınız new
:
String s = String();
karşı
String s = new String();
çünkü new
anahtar sözcük içermeyen çağrı, String
bağımsız değişkenler olmadan çağrılan (yerel) bir yöntemi deneyecek ve arayacaktır - ve bu yöntem imzası büyük olasılıkla tanımlanmamıştır.
'Değişken kapsam dışı' için bir örnek daha
Bu tür soruları daha önce birkaç kez gördüğüm gibi, iyi hissettirse bile neyin yasadışı olduğuna dair bir örnek daha olabilir .
Bu kodu düşünün:
if(somethingIsTrue()) {
String message = "Everything is fine";
} else {
String message = "We have an error";
}
System.out.println(message);
Bu geçersiz kod. Çünkü adı geçen değişkenlerin hiçbiri message
kendi kapsamlarının dışında görünmez - {}
bu durumda bu parantezleri çevreleyen parantezler olacaktır .
Sen diyebilirsiniz: "Ama bu mesaj adında bir değişken her iki şekilde tanımlanır - mesaj böylece edilir sonra tanımlanmış if
".
Ama yanılıyorsun.
Java'nın hiçbir free()
veya delete
operatörü yoktur , bu nedenle değişkenlerin artık ne zaman kullanılmadığını öğrenmek için değişken kapsamını izlemeye güvenmek zorundadır (bu neden değişkenlerine referanslarla birlikte).
İyi bir şey yaptığınızı düşünmeniz özellikle kötüdür. Kodu şöyle "optimize ettikten" sonra bu tür bir hatayla karşılaştım:
if(somethingIsTrue()) {
String message = "Everything is fine";
System.out.println(message);
} else {
String message = "We have an error";
System.out.println(message);
}
"Oh, yinelenen kod var, hadi şu ortak satırı çıkaralım" -> ve işte orada.
Bu tür kapsam sorunuyla başa çıkmanın en yaygın yolu, else değerlerini dış kapsamdaki değişken adlarına önceden atamak ve ardından aşağıdaki durumlarda yeniden atamaktır:
String message = "We have an error";
if(somethingIsTrue()) {
message = "Everything is fine";
}
System.out.println(message);
Eclipse'de bu hatayı almanın bir yolu:
- Bir sınıf tanımlayın
A
içindesrc/test/java
. - Başka bir sınıf tanımlayın
B
içindesrc/main/java
that use sınıfındaA
.
Sonuç: Eclipse kodu derleyecek, ancak maven "Sembol bulunamıyor" verecektir.
Temel neden: Eclipse, ana ve test ağaçları için birleşik bir oluşturma yolu kullanıyor. Ne yazık ki, bir Eclipse projesinin farklı bölümleri için farklı derleme yollarının kullanılmasını desteklemiyor, Maven bunu gerektiriyor.
Çözüm :
- Bağımlılıklarınızı bu şekilde tanımlamayın; yani bu hatayı yapmayın.
- Maven kullanarak kod tabanınızı düzenli olarak oluşturun, böylece bu hatayı erkenden fark edebilirsiniz. Bunu yapmanın bir yolu, bir CI sunucusu kullanmaktır.
"Bulunamıyor", uygun değişken, yöntem, sınıf vb. Bulamayan derleyici anlamına gelir ... eğer bu hata masajını aldıysanız, öncelikle hata masajı alacağınız kod satırını bulmak istiyorsunuz ... Ve sonra Kullanmadan önce hangi değişken, yöntem veya sınıfın tanımlamadığını bulabilir. Onaylandıktan sonra bu değişken, yöntem veya sınıf daha sonra kullanılabilir. Aşağıdaki örneği düşünün.
Bir demo sınıfı oluşturacağım ve bir isim yazdıracağım ...
class demo{
public static void main(String a[]){
System.out.print(name);
}
}
Şimdi sonuca bakın ..
Bu hata, "değişken adı bulunamıyor" diyor .. "İsim" değişkeni için değer tanımlama ve başlatma bu hatayı ortadan kaldırabilir ... Aslında böyle,
class demo{
public static void main(String a[]){
String name="smith";
System.out.print(name);
}
}
Şimdi yeni çıktıya bakın ...
Tamam Bu hatayı başarıyla çözdüm ... Aynı zamanda "yöntem bulamıyorum" veya "sınıf bulamıyorum" gibi bir şey alabiliyorsanız, önce bir sınıf veya yöntem tanımlayın ve sonra onu kullanın ..
Bu hatayı yapıda başka bir yerde alıyorsanız, IDE'niz her şeyin mükemmel olduğunu söylerken, o zaman her iki yerde de aynı Java sürümlerini kullandığınızı kontrol edin.
Örneğin, Java 7 ve Java 8'in farklı API'leri vardır, bu nedenle daha eski bir Java sürümünde var olmayan bir API'yi çağırmak bu hataya neden olur.
ÇÖZÜLDÜ
IntelliJ kullanma
Seç Yapı -> Proje Yeniden çözecek
Ben de bu hatayı alıyordum. (bunun için googledim ve bu sayfaya yönlendirildim)
Sorun: Başka bir B projesinde tanımlanan bir sınıftan A projesi sınıfında tanımlanan statik bir yöntemi çağırıyordum.Aşağıdaki hatayı alıyordum:
error: cannot find symbol
Çözüm: Bunu önce yöntemin tanımlandığı projeyi, ardından yöntemin çağrıldığı projeyi oluşturarak çözdüm.
Eclipse Java derleme yolu 7, 8 ile eşlenmişse ve Project pom.xml Maven properties java.version'da 7,8'den daha yüksek Java sürümünden (9,10,11, vb.) Bahsediliyorsa, pom'da güncellemeniz gerekir. xml dosyası.
Eclipse'de Java, Java sürüm 11 ile eşlenirse ve pom.xml'de Java sürüm 8 ile eşlenir. Eclipse IDE Yardımı -> Yeni Yazılım Yükle -> bölümünde aşağıdaki adımları izleyerek Eclipse desteğini Java 11'e güncelleyin ->
Aşağıdaki bağlantıyı yapıştırın http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With
veya
Ekle (Popup penceresi açılacaktır) ->
Name:
Java 11 desteği
Location:
http://download.eclipse.org/eclipse/updates/4.9-P-builds
ardından aşağıdaki gibi pom.xml dosyasının Maven özelliklerinde Java sürümünü güncelleyin
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
Son olarak Debug as projesine sağ tıklayın -> Maven clean, Maven build steps
İnsanların yukarıda bahsettiği gibi çeşitli senaryolar olabilir. Bunu çözmeme yardımcı olan birkaç şey.
IntelliJ kullanıyorsanız
File -> 'Invalidate Caches/Restart'
VEYA
Başvurulan sınıf başka bir projedeydi ve bu bağımlılık projemin Gradle derleme dosyasına eklenmedi. Bu yüzden bağımlılığı ekledim
compile project(':anotherProject')
ve işe yaradı. HTH!
Kodunuzu maven derlemesini kullanarak derlediniz ve daha sonra çalıştırmak için maven testini kullandınız. Şimdi kodunuzdaki bir şeyi değiştirdiyseniz ve sonra derlemeden çalıştırıyorsanız, bu hatayı alırsınız.
Çözüm: Tekrar derleyin ve ardından testi çalıştırın. Benim için bu şekilde çalıştı.
Benim durumumda - aşağıdaki işlemleri yapmak zorunda kaldım:
- Taşı
context.xml
dosyayısrc/java/package
içinresource
dizine (IntelliJ IDE) - Temiz
target
dizin.
İpuçları için, hata veren sınıf adına ve satır numarasına daha yakından bakın, örneğin: Derleme hatası [HATA] \ uygulamalar \ xxxxx.java: [44,30] hatası: sembol bulunamıyor
Diğer bir neden de desteklenmeyen bir yöntem olan java sürümü için jdk7 vs 8 diyelim.% JAVA_HOME%
Gradle çoklu proje derlemesi olarak ayarlanmış bir Java projesinde hatayı aldık. Alt projelerden birinde Gradle Java Library eklentisinin eksik olduğu ortaya çıktı . Bu, alt projenin sınıf dosyalarının yapıdaki diğer projelere görünür olmasını engelledi.
Java kitaplığı eklentisini build.gradle
aşağıdaki şekilde alt projelere ekledikten sonra , hata ortadan kalktı:
plugins {
...
id 'java-library'
}
Ben bu hatayı şöyle çözdüm ... Android'in çılgınlığı. Paket adını Adapter olarak aldım ve bağdaştırıcının adını "A" yerine "a" ile yeniden düzenledim ve hatayı çözdüm.