ข้อผิดพลาด“ ไม่สามารถหาสัญลักษณ์” หรือ“ ไม่สามารถแก้ไขสัญลักษณ์” หมายความว่าอะไร


395

โปรดอธิบายต่อไปนี้เกี่ยวกับข้อผิดพลาด "ไม่สามารถหาสัญลักษณ์" และ "ไม่สามารถแก้ไขสัญลักษณ์":

  • พวกเขาหมายถึงอะไร?
  • สิ่งใดที่สามารถทำให้พวกเขา
  • โปรแกรมเมอร์ไปเกี่ยวกับการแก้ไขได้อย่างไร

คำถามนี้ได้รับการออกแบบมาเพื่อรวบรวมคำถามและคำตอบที่ครอบคลุมเกี่ยวกับข้อผิดพลาดทั่วไปในการรวบรวมใน Java

คำตอบ:


417

0. ข้อแตกต่างระหว่างสองข้อผิดพลาดหรือไม่?

ไม่ได้จริงๆ "ไม่สามารถหาสัญลักษณ์" และ "ไม่สามารถแก้ไขสัญลักษณ์" หมายถึงสิ่งเดียวกัน คอมไพเลอร์ Java บางตัวใช้วลีเดียวและอีกอันหนึ่งคอมไพเลอร์อื่น ๆ

1. ข้อผิดพลาด "ไม่สามารถหาสัญลักษณ์" หมายความว่าอย่างไร

ประการแรกก็คือการรวบรวมข้อผิดพลาด 1 หมายความว่าอาจมีปัญหาในซอร์สโค้ด Java ของคุณหรือมีปัญหาในแบบที่คุณคอมไพล์

ซอร์สโค้ด Java ของคุณประกอบด้วยสิ่งต่าง ๆ ดังต่อไปนี้:

  • คำสำคัญ: เช่นtrue, false, class, whileและอื่น ๆ
  • ตัวอักษร: เหมือน42และและ'X'"Hi mum!"
  • ผู้ประกอบการและราชสกุลไม่ใช่ตัวเลขอื่น ๆ เช่น+, =, {และอื่น ๆ
  • ตัวบ่งชี้: เช่นReader, i, toString, processEquibalancedElephantsและอื่น ๆ
  • ความคิดเห็นและช่องว่าง

ข้อผิดพลาด "ไม่พบสัญลักษณ์" เป็นเรื่องเกี่ยวกับตัวระบุ เมื่อคอมไพล์โค้ดของคุณคอมไพเลอร์จำเป็นต้องหาตัวบ่งชี้แต่ละตัวในโค้ดของคุณ

ข้อผิดพลาด "ไม่สามารถหาสัญลักษณ์" หมายความว่าคอมไพเลอร์ไม่สามารถทำได้ รหัสของคุณดูเหมือนจะอ้างถึงบางสิ่งที่คอมไพเลอร์ไม่เข้าใจ

2. ข้อผิดพลาด "หาสัญลักษณ์ไม่พบ" คืออะไร

ในการสั่งซื้อครั้งแรกมีเพียงสาเหตุเดียวเท่านั้น คอมไพเลอร์ดูในสถานที่ทั้งหมดที่ควรกำหนดตัวระบุและไม่พบคำจำกัดความ สิ่งนี้อาจเกิดจากหลายสิ่ง คนทั่วไปมีดังนี้:

  • สำหรับตัวระบุโดยทั่วไป:
    • บางทีคุณสะกดชื่อไม่ถูกต้อง คือแทนStringBiulder StringBuilderJava ไม่สามารถและจะไม่พยายามชดเชยการสะกดผิดหรือการพิมพ์ผิดพลาด
    • คุณอาจเข้าใจผิด คือแทนstringBuilder StringBuilderตัวระบุ Java ทั้งหมดต้องตรงตามตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก
    • บางทีคุณอาจใช้ขีดเส้นใต้ที่ไม่เหมาะสม เช่นmystringและmy_stringแตกต่างกัน (ถ้าคุณยึดติดกับกฎสไตล์ Java คุณจะได้รับการปกป้องส่วนใหญ่จากความผิดพลาดนี้ ... )
    • บางทีคุณกำลังพยายามใช้บางสิ่งที่ถูกประกาศว่า "ที่อื่น"; เช่นในบริบทที่แตกต่างกันซึ่งคุณได้บอกให้คอมไพเลอร์ดูโดยปริยาย (คลาสที่แตกต่างกันอย่างไรขอบเขตที่แตกต่างกันแพคเกจที่แตกต่างกันหรือมีรหัสฐานที่แตกต่างกัน)
  • สำหรับตัวระบุที่ควรอ้างถึงตัวแปร:
    • บางทีคุณลืมที่จะประกาศตัวแปร
    • บางทีการประกาศตัวแปรนั้นไม่อยู่ในขอบเขตที่คุณพยายามจะใช้ (ดูตัวอย่างด้านล่าง)
  • สำหรับตัวระบุที่ควรเป็นชื่อเมธอดหรือฟิลด์:

    • บางทีคุณกำลังพยายามอ้างถึงวิธีการหรือฟิลด์ที่สืบทอดซึ่งไม่ได้ประกาศไว้ในคลาสหรืออินเทอร์เฟซหลัก / บรรพบุรุษ
    • บางทีคุณกำลังพยายามอ้างถึงวิธีหรือเขตข้อมูลที่ไม่มีอยู่ (เช่นยังไม่ได้ประกาศ) ในประเภทที่คุณกำลังใช้ เช่น2"someString".push()
    • บางทีคุณกำลังพยายามใช้วิธีการเป็นเขตข้อมูลหรือในทางกลับกัน เช่นหรือ"someString".lengthsomeArray.length()
    • บางทีคุณอาจทำงานผิดพลาดในอาร์เรย์มากกว่าองค์ประกอบอาร์เรย์; เช่น

      String strings[] = ...
      if (strings.charAt(3)) { ... }
      // maybe that should be 'strings[0].charAt(3)'
  • สำหรับตัวระบุที่ควรเป็นชื่อคลาส:

    • บางทีคุณลืมที่จะนำเข้าชั้นเรียน
    • บางทีคุณอาจใช้การนำเข้า "ดาว" แต่ไม่ได้กำหนดคลาสไว้ในแพ็คเกจใด ๆ ที่คุณนำเข้า
    • บางทีคุณอาจลืมnewใน:

      String s = String();  // should be 'new String()'
  • สำหรับกรณีที่ประเภทหรืออินสแตนซ์ไม่ปรากฏว่ามีสมาชิกคุณคาดว่าจะมี:

    • บางทีคุณอาจจะมีการประกาศให้เป็นชั้นซ้อนกันหรือพารามิเตอร์ทั่วไปที่เงาชนิดที่คุณหมายถึงการใช้
    • บางทีคุณอาจกำลังแรเงาตัวแปรแบบคงที่หรืออินสแตนซ์
    • บางทีคุณอาจนำเข้าประเภทที่ไม่ถูกต้อง เช่นเนื่องจากความสมบูรณ์ของ IDE หรือการแก้ไขอัตโนมัติ
    • บางทีคุณอาจกำลังใช้ API ที่รวบรวมผิดเวอร์ชัน
    • บางทีคุณอาจลืมโยนวัตถุของคุณไปยังคลาสย่อยที่เหมาะสม

ปัญหานี้มักจะเป็นการรวมกันของข้างต้น ตัวอย่างเช่นคุณอาจ "ดาว" นำเข้าjava.io.*แล้วลองใช้Filesคลาส ... ซึ่งjava.nioไม่java.ioอยู่ หรือบางทีคุณอาจหมายถึงการเขียนFile... ซึ่งเป็นjava.ioชั้นใน


นี่คือตัวอย่างของการกำหนดขอบเขตตัวแปรที่ไม่ถูกต้องสามารถนำไปสู่ข้อผิดพลาด "ไม่พบสัญลักษณ์":

List<String> strings = ...

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

สิ่งนี้จะทำให้เกิดข้อผิดพลาด "ไม่พบสัญลักษณ์" iในifคำสั่ง แม้ว่าเราจะประกาศก่อนหน้านี้การประกาศiนั้นอยู่ในขอบเขตของforข้อความและเนื้อหาเท่านั้น อ้างอิงถึงiในifคำสั่งไม่สามารถดูiการประกาศว่า มันเป็นออกจากขอบเขต

(การแก้ไขที่เหมาะสมที่นี่อาจเป็นการย้ายifคำสั่งภายในลูปหรือประกาศiก่อนเริ่มลูป)


นี่คือตัวอย่างที่ทำให้เกิดข้อผิดพลาดที่การพิมพ์ผิดนำไปสู่ข้อผิดพลาด "ไม่พบสัญลักษณ์" ที่อธิบายไม่ได้:

for (int i = 0; i < 100; i++); {
    System.out.println("i is " + i);
}

สิ่งนี้จะทำให้คุณรวบรวมข้อผิดพลาดในการprintlnโทรโดยบอกว่าiไม่พบ แต่ (ฉันได้ยินคุณพูด) ฉันประกาศ!

ปัญหาคืออัฒภาคส่อเสียด ( ;) {ก่อน ไวยากรณ์ภาษา Java กำหนดอัฒภาคในบริบทที่จะเป็นคำสั่งที่ว่างเปล่า คำสั่งที่ว่างเปล่าจะกลายเป็นเนื้อความของforลูป ดังนั้นรหัสที่จริงหมายถึงสิ่งนี้:

for (int i = 0; i < 100; i++); 

// The previous and following are separate statements!!

{
    System.out.println("i is " + i);
}

{ ... }บล็อกไม่ได้ร่างกายของforวงและดังนั้นจึงประกาศก่อนหน้านี้iในforคำสั่งออกจากขอบเขตในบล็อก


นี่เป็นอีกตัวอย่างของข้อผิดพลาด "ไม่สามารถหาสัญลักษณ์" ที่เกิดจากการพิมพ์ผิด

int tmp = ...
int res = tmp(a + b);

แม้จะมีการประกาศก่อนหน้านี้tmpในการtmp(...)แสดงออกที่ไม่ถูกต้อง คอมไพเลอร์จะมองหาวิธีที่เรียกว่าtmpและจะไม่พบวิธีใดวิธีหนึ่ง ประกาศก่อนหน้านี้tmpอยู่ใน namespace สำหรับตัวแปรไม่ใช่ namespace สำหรับวิธีการ

ในตัวอย่างที่ฉันเจอผู้เขียนได้ทิ้งโอเปอเรเตอร์จริงๆ สิ่งที่เขาตั้งใจจะเขียนคือ:

int res = tmp * (a + b);

มีอีกเหตุผลที่คอมไพเลอร์อาจไม่พบสัญลักษณ์หากคุณกำลังรวบรวมจากบรรทัดคำสั่ง คุณอาจลืมรวบรวมหรือคอมไพล์คลาสอื่น ๆ ตัวอย่างเช่นถ้าคุณมีชั้นเรียนFooและBarที่ใช้Foo Barหากคุณไม่เคยคอมไพล์Barและรันjavac Foo.javaคุณจะต้องพบว่าคอมไพเลอร์ไม่สามารถหาสัญลักษณ์Barได้ คำตอบง่ายๆคือรวบรวมFooและBarรวมกัน; เช่นหรือjavac Foo.java Bar.java javac *.javaหรือดีกว่ายังคงใช้เครื่องมือสร้าง Java; เช่น Ant, Maven, Gradle และอื่น ๆ

มีสาเหตุอื่นที่ไม่ชัดเจนอีกด้วย ... ซึ่งฉันจะจัดการกับด้านล่าง

3. ฉันจะแก้ไขข้อผิดพลาดเหล่านี้ได้อย่างไร

โดยทั่วไปคุณจะเริ่มต้นด้วยการหาสาเหตุที่ทำให้เกิดข้อผิดพลาดในการรวบรวม

  • ดูบรรทัดในไฟล์ที่ระบุโดยข้อความแสดงข้อผิดพลาดการคอมไพล์
  • ระบุสัญลักษณ์ที่ข้อความแสดงข้อผิดพลาดกำลังพูดถึง
  • หาสาเหตุที่คอมไพเลอร์บอกว่าไม่สามารถหาสัญลักษณ์ได้ ดูด้านบน!

จากนั้นคุณคิดว่ารหัสของคุณควรจะพูดอะไร จากนั้นในที่สุดคุณก็จะทำการแก้ไขสิ่งที่คุณต้องทำกับซอร์สโค้ดของคุณเพื่อทำสิ่งที่คุณต้องการ

โปรดทราบว่าไม่ใช่ "การแก้ไข" ทุกอย่างที่ถูกต้อง พิจารณาสิ่งนี้:

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

สมมติว่าคอมไพเลอร์กล่าวว่า "คุณไม่พบสัญลักษณ์" jสำหรับ มีหลายวิธีที่ฉันสามารถ "แก้ไข" ที่:

  • ฉันสามารถเปลี่ยนด้านในforเป็นfor (int j = 1; j < 10; j++)- อาจถูกต้อง
  • ฉันสามารถเพิ่มการประกาศสำหรับj ก่อนforวงด้านในหรือforวงด้านนอก- อาจถูกต้อง
  • ผมอาจมีการเปลี่ยนแปลงjไปiในด้านforห่วง - อาจผิด!
  • และอื่น ๆ

ประเด็นก็คือคุณต้องเข้าใจว่าโค้ดของคุณพยายามทำอะไรเพื่อหาวิธีแก้ไขที่ถูกต้อง

4. สาเหตุที่ไม่ชัดเจน

นี่คือบางกรณีที่ "ไม่สามารถหาสัญลักษณ์" ดูเหมือนจะอธิบายไม่ได้ ... จนกว่าคุณจะเข้าใกล้

  1. การอ้างอิงที่ไม่ถูกต้อง : ถ้าคุณใช้ IDE หรือเครื่องมือบิลด์ที่จัดการพา ธ การ build และการพึ่งพาโปรเจ็กต์คุณอาจทำผิดกับการพึ่งพา เช่นออกจากการพึ่งพาหรือเลือกรุ่นที่ไม่ถูกต้อง หากคุณใช้เครื่องมือบิลด์ (Ant, Maven, Gradle, ฯลฯ ) ให้ตรวจสอบไฟล์บิลด์ของโปรเจ็กต์ หากคุณใช้ IDE ให้ตรวจสอบการกำหนดค่าเส้นทางของโครงการ

  2. คุณไม่ได้ทำการคอมไพล์ใหม่ : บางครั้งมันเกิดขึ้นที่โปรแกรมเมอร์ Java คนใหม่ไม่เข้าใจว่าเครื่องมือของ Java ทำงานอย่างไรหรือไม่ได้ใช้ "build process" ซ้ำ เช่นใช้ IDE, Ant, Maven, Gradle และอื่น ๆ ในสถานการณ์เช่นโปรแกรมเมอร์ที่สามารถจบลงไล่หางของเขามองหาข้อผิดพลาดที่ไม่จริงที่เป็นจริงที่เกิดจากการไม่ recompiling รหัสได้อย่างถูกต้องและไม่ชอบ ...

  3. ปัญหาบิลด์ก่อนหน้า : เป็นไปได้ว่าบิลด์ก่อนหน้านี้ล้มเหลวในลักษณะที่ให้ไฟล์ JAR ที่มีคลาสที่หายไป ความล้มเหลวดังกล่าวมักจะสังเกตเห็นว่าคุณกำลังใช้เครื่องมือสร้าง อย่างไรก็ตามหากคุณได้รับไฟล์ JAR จากบุคคลอื่นคุณจะต้องพึ่งพาพวกเขาในการสร้างไฟล์อย่างถูกต้องและสังเกตเห็นข้อผิดพลาด หากคุณสงสัยว่าสิ่งนี้ใช้tar -tvfเพื่อแสดงรายการเนื้อหาของไฟล์ JAR ที่น่าสงสัย

  4. ปัญหา IDE : ผู้คนรายงานกรณีที่ IDE สับสนและคอมไพเลอร์ใน IDE ไม่สามารถหาคลาสที่มีอยู่ ... หรือสถานการณ์ย้อนกลับ

    • สิ่งนี้อาจเกิดขึ้นหาก IDE ได้รับการกำหนดค่าด้วยรุ่น JDK ผิด

    • สิ่งนี้อาจเกิดขึ้นได้หากแคชของ IDE ไม่สอดคล้องกับระบบไฟล์ มีวิธีเฉพาะของ IDE ในการแก้ไขปัญหานี้

    • นี่อาจเป็นข้อบกพร่องของ IDE ตัวอย่างเช่น @Joel Costigliola อธิบายสถานการณ์ที่ Eclipse ไม่จัดการทรี Maven "test" อย่างถูกต้อง: ดูคำตอบนี้

  5. ประเด็น Android : เมื่อคุณเขียนโปรแกรมสำหรับ Android และคุณมี "ไม่สามารถหาสัญลักษณ์" ข้อผิดพลาดที่เกี่ยวข้องกับการRจะทราบว่าRสัญลักษณ์ถูกกำหนดโดยcontext.xmlไฟล์ ตรวจสอบว่าcontext.xmlไฟล์ของคุณถูกต้องและอยู่ในตำแหน่งที่ถูกต้องและRไฟล์คลาสที่เกี่ยวข้องนั้นถูกสร้างขึ้น / รวบรวม โปรดทราบว่าสัญลักษณ์ Java เป็นแบบตรงตามตัวพิมพ์ใหญ่ - เล็กดังนั้นรหัส XML ที่สอดคล้องกันจะต้องตรงตามตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก

    ข้อผิดพลาดของสัญลักษณ์อื่น ๆ บน Android น่าจะเกิดจากสาเหตุที่กล่าวถึงก่อนหน้านี้; เช่นการพึ่งพาที่ขาดหายไปหรือไม่ถูกต้องชื่อแพคเกจที่ไม่ถูกต้องวิธีการหรือฟิลด์ที่ไม่มีอยู่ใน API รุ่นใดรุ่นหนึ่งข้อผิดพลาดด้านการสะกดคำ / การพิมพ์และอื่น ๆ

  6. การกำหนดคลาสระบบใหม่ : ฉันเคยเห็นกรณีที่คอมไพเลอร์บ่นว่าsubstringเป็นสัญลักษณ์ที่ไม่รู้จักในบางสิ่งดังต่อไปนี้

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

    มันกลับกลายเป็นว่าโปรแกรมเมอร์ได้สร้างเวอร์ชันของตนเองขึ้นมาStringและรุ่นของคลาสนั้นไม่ได้กำหนดsubstringวิธีการ

    บทเรียน: อย่ากำหนดคลาสของคุณเองด้วยชื่อเดียวกับคลาสไลบรารีทั่วไป!

  7. Homoglyphs: หากคุณใช้การเข้ารหัส UTF-8 สำหรับไฟล์ต้นฉบับของคุณเป็นไปได้ที่จะมีตัวระบุที่มีลักษณะเหมือนกัน แต่ในความเป็นจริงแตกต่างกันเนื่องจากมี homoglyphs ดูหน้านี้สำหรับข้อมูลเพิ่มเติม

    คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดย จำกัด ตัวเองเป็น ASCII หรือ Latin-1 เป็นการเข้ารหัสไฟล์ต้นฉบับและใช้ Java \uxxxxescapes สำหรับอักขระอื่น ๆ


1 - ถ้าบางทีคุณไม่เห็นนี้ในข้อยกเว้นรันไทม์หรือข้อผิดพลาดแล้วทั้งคุณได้กำหนดค่า IDE ของคุณเพื่อเรียกใช้รหัสมีข้อผิดพลาดการรวบรวมหรือใบสมัครของคุณคือการสร้างและรวบรวมรหัส .. ที่รันไทม์

2 - หลักการพื้นฐานสามประการของวิศวกรรมโยธา: น้ำไม่ไหลขึ้นเขากระดานมีความแข็งแรงกว่าและคุณไม่สามารถดันสายได้


ฉันมีสถานการณ์อื่นที่ข้อผิดพลาดการรวบรวมนี้เกิดขึ้นในขณะที่ eclipse ไม่เห็นปัญหา: สองคลาสที่มีการอ้างอิงที่กำหนดไว้ในคลาสอื่นตามลำดับ ในกรณีของฉันฉันมี enum ติดตั้งอินเตอร์เฟสที่กำหนดไว้ในคลาสที่ฉันใช้ enum อย่างโง่เขลา
Jogi

ค่อนข้างคล้ายกับความคิดเห็นข้างต้นเมื่อฉันรวบรวมและเรียกใช้โปรแกรมจาก Eclipse มันไม่มีปัญหา การรวบรวมจากคอนโซลจะทำให้เกิดข้อผิดพลาด "ไม่พบสัญลักษณ์" ซึ่งมักเกี่ยวข้องกับองค์ประกอบสุดท้ายในการนำเข้า ฉันไม่รู้ว่าอะไรเป็นสาเหตุของเรื่องนี้เพราะไม่มีอะไรผิดปกติในรหัสจริงๆ
Andres Stadelmann

ปัญหาอื่นคือ IDEs อาจ "ตีความ" ข้อผิดพลาดอื่น ๆ ลงในหมวดหมู่นี้ ยกตัวอย่างเช่นprintlnในSystem.out.printlnหากวางอยู่ในระดับชั้นภายใต้มาตรฐานคอมไพเลอร์จะให้เรา<identifier> expected( สาธิต ) แต่ใน IntelliJ เราจะเห็นCannot resolve symbol 'println'( สาธิต )
Pshemo

ว้าว. ฉันจะเรียกว่าข้อผิดพลาดของคอมไพเลอร์
Stephen C

23

คุณจะได้รับข้อผิดพลาดนี้หากคุณลืมnew:

String s = String();

กับ

String s = new String();

เนื่องจากการโทรที่ไม่มีnewคำหลักจะพยายามมองหาวิธี (ภายใน) ที่เรียกว่าStringไม่มีอาร์กิวเมนต์ - และอาจไม่ได้กำหนดลายเซ็นของวิธีนั้น


14

อีกหนึ่งตัวอย่างของ 'ตัวแปรที่อยู่นอกขอบเขต'

ในฐานะที่ผมเคยเห็นว่าชนิดของคำถามไม่กี่ครั้งแล้วตัวอย่างเช่นอาจจะเป็นหนึ่งมากขึ้นสิ่งที่ผิดกฎหมายแม้ว่ามันอาจจะรู้สึกว่าโอเค

พิจารณารหัสนี้:

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

นั่นเป็นรหัสที่ไม่ถูกต้อง เนื่องจากตัวแปรที่ตั้งชื่อmessageไม่สามารถมองเห็นได้นอกขอบเขตที่เกี่ยวข้อง - ซึ่งจะเป็นวงเล็บเหลี่ยมโดยรอบ{}ในกรณีนี้

คุณอาจพูดว่า: "แต่ตัวแปรชื่อข้อความถูกกำหนดอย่างใดอย่างหนึ่ง - ดังนั้นข้อความจะถูกกำหนดหลังจากif"

แต่คุณจะผิด

Java ไม่มีfree()หรือdeleteตัวดำเนินการดังนั้นจึงต้องอาศัยการติดตามขอบเขตตัวแปรเพื่อค้นหาว่าเมื่อใดที่ตัวแปรจะไม่ถูกใช้อีกต่อไป (พร้อมกับการอ้างอิงถึงตัวแปรของสาเหตุเหล่านี้)

มันแย่มากถ้าคุณคิดว่าคุณทำสิ่งที่ดี ฉันเห็นข้อผิดพลาดประเภทนี้หลังจากรหัส "การเพิ่มประสิทธิภาพ" เช่นนี้:

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

"โอ้มีรหัสที่ซ้ำกันมาดึงบรรทัดทั่วไปออกมา" -> แล้วค่อยมา

วิธีที่ใช้กันมากที่สุดในการจัดการกับขอบเขตของปัญหานี้คือการกำหนดค่าอื่นให้กับชื่อตัวแปรในขอบเขตภายนอกแล้วกำหนดใหม่หาก:

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

4
"Java ไม่มีตัวให้บริการฟรี () หรือลบดังนั้นจึงต้องอาศัยการติดตามขอบเขตตัวแปรเพื่อค้นหาว่าเมื่อใดที่ตัวแปรจะไม่ถูกใช้อีกต่อไป (รวมถึงการอ้างอิงถึงสาเหตุของตัวแปรเหล่านี้)" - ในขณะที่เป็นจริงสิ่งนี้ไม่เกี่ยวข้อง C และ C ++ มีตัวดำเนินการอิสระ / ลบตามลำดับ แต่รหัส C / C ++ ที่เทียบเท่ากับตัวอย่างของคุณอาจผิดกฎหมาย บล็อก C และ C ++ จำกัด ขอบเขตของตัวแปรเช่นเดียวกับใน Java อันที่จริงสิ่งนี้เป็นจริงสำหรับภาษา "บล็อกโครงสร้าง" ส่วนใหญ่
สตีเฟนซี

1
ทางออกที่ดีกว่าสำหรับรหัสที่กำหนดค่าที่แตกต่างกันในทุกสาขาคือการใช้การประกาศตัวแปรว่าง final
Daniel Pryden

10

วิธีหนึ่งในการรับข้อผิดพลาดนี้ใน Eclipse:

  1. กำหนดชั้นเรียนในAsrc/test/java
  2. กำหนดอีกชั้นBในที่ใช้ในชั้นเรียนsrc/main/javaA

ผลลัพธ์: Eclipse จะรวบรวมรหัส แต่ maven จะให้ "ไม่สามารถหาสัญลักษณ์"

สาเหตุสำคัญ: Eclipse ใช้พา ธ บิลด์รวมสำหรับแผนผังหลักและต้นไม้ทดสอบ น่าเสียดายที่มันไม่สนับสนุนการใช้พา ธ บิลด์ที่แตกต่างกันสำหรับส่วนต่างๆของโครงการ Eclipse ซึ่งเป็นสิ่งที่ Maven ต้องการ

สารละลาย :

  1. อย่ากำหนดการพึ่งพาของคุณในวิธีนั้น คืออย่าทำผิดพลาด
  2. สร้าง codebase เป็นประจำโดยใช้ Maven เพื่อให้คุณรับความผิดพลาดนี้ตั้งแต่เนิ่นๆ วิธีหนึ่งในการทำเช่นนั้นคือการใช้เซิร์ฟเวอร์ CI

อะไรคือทางออกของปัญหานี้?

2
สิ่งที่คุณใช้ใน src / main / java จำเป็นต้องกำหนดไว้ใน src / main / java หรือในการคอมไพล์ / การพึ่งพารันไทม์ใด ๆ (ไม่ใช่การทดสอบการขึ้นต่อกัน)
Joel Costigliola

5

"ไม่สามารถหา" หมายความว่าคอมไพเลอร์ที่ไม่สามารถหาตัวแปรที่เหมาะสมวิธีการเรียน ฯลฯ ... หากคุณได้รับการนวดข้อผิดพลาดก่อนอื่นคุณต้องค้นหารหัสบรรทัดที่ได้รับการนวดผิดพลาด .. แล้วคุณจะ สามารถค้นหาตัวแปรวิธีการหรือคลาสที่ไม่ได้กำหนดไว้ก่อนใช้งานหลังจากการยืนยันเริ่มต้นตัวแปรวิธีการหรือคลาสที่สามารถใช้ในภายหลังจำเป็นต้องใช้ ... พิจารณาตัวอย่างต่อไปนี้

ฉันจะสร้างคลาสตัวอย่างและพิมพ์ชื่อ ...

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

ตอนนี้ดูที่ผล ..

ป้อนคำอธิบายรูปภาพที่นี่

ข้อผิดพลาดนั้นบอกว่า "ชื่อตัวแปรไม่สามารถหาได้" .. การกำหนดและกำหนดค่าเริ่มต้นสำหรับตัวแปร 'ชื่อ' สามารถยกเลิกข้อผิดพลาดนั้นได้จริงเช่นนี้

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

             String name="smith";

             System.out.print(name);
      }
}

ตอนนี้ดูผลลัพธ์ใหม่ ...

ป้อนคำอธิบายรูปภาพที่นี่

ตกลงประสบความสำเร็จในการแก้ไขข้อผิดพลาดนั้น .. ในเวลาเดียวกันถ้าคุณได้รับ "ไม่สามารถหาวิธีการ" หรือ "ไม่สามารถหาชั้นเรียน" บางอย่างในตอนแรกกำหนดชั้นเรียนหรือวิธีการและหลังการใช้ ..


3

หากคุณได้รับข้อผิดพลาดนี้ในการสร้างที่อื่นในขณะที่ IDE ของคุณบอกว่าทุกอย่างเรียบร้อยดีแล้วให้ตรวจสอบว่าคุณใช้ Java เวอร์ชันเดียวกันทั้งสองแห่ง

ตัวอย่างเช่น Java 7 และ Java 8 มี API ที่แตกต่างกันดังนั้นการเรียก API ที่ไม่มีอยู่ใน Java เวอร์ชันเก่าจะทำให้เกิดข้อผิดพลาดนี้


2

ฉันก็รับข้อผิดพลาดนี้เช่นกัน (ซึ่งฉัน googled และฉันถูกนำไปยังหน้านี้)

ปัญหา:ฉันเรียกวิธีสแตติกที่กำหนดไว้ในคลาสของโปรเจ็กต์ A จากคลาสที่กำหนดในโปรเจ็กต์อื่น B ​​ฉันได้รับข้อผิดพลาดต่อไปนี้:

error: cannot find symbol

การแก้ไข:ฉันแก้ไขปัญหานี้โดยการสร้างโครงการที่มีการกำหนดวิธีการก่อนจากนั้นโครงการที่มีการเรียกวิธีการนั้น


ใช่สิ่งนี้อาจเกิดขึ้นได้หากคุณตัดสินใจที่จะย้ายฟังก์ชั่นที่สามารถนำกลับมาใช้ใหม่จากแพ็คเกจปัจจุบันของคุณไปยังแพ็คเกจ utils ทั่วไปของคุณได้ แต่จากนั้นคุณลืมคอมไพล์แพคเกจทั่วไปก่อนเรียกใช้ฟังก์ชันจากแพ็คเกจปัจจุบัน
buildingKofi

2

หากพา ธ การสร้าง eclipse Java ถูกแม็พกับ 7, 8 และใน Project pom.xml คุณสมบัติ Maven java.version กล่าวถึงเวอร์ชัน Java ที่สูงกว่า (9,10,11, ฯลฯ .. ) กว่า 7,8 คุณต้องอัปเดตเป็น pom ไฟล์ xml

ใน Eclipse หาก Java ถูกแมปกับ Java เวอร์ชัน 11 และใน pom.xml จะถูกแมปกับ Java เวอร์ชัน 8 อัปเดตการสนับสนุน Eclipse เป็น Java 11 โดยทำตามขั้นตอนด้านล่างในวิธีใช้ eclipse IDE -> ติดตั้งซอฟต์แวร์ใหม่ ->

วางลิงค์ต่อไปนี้http://download.eclipse.org/eclipse/updates/4.9-P-buildsที่Work With

หรือ

เพิ่ม (หน้าต่างป๊อปอัพจะเปิด) ->

Name:Java 11 รองรับ Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

จากนั้นอัพเดตเวอร์ชัน Java ในคุณสมบัติ Maven ของไฟล์pom.xmlดังนี้

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

ในที่สุดคลิกขวาที่ Debug โครงการเป็น -> Maven clean, Maven build steps


2

แก้ไข

เลือกสร้าง -> สร้างโครงการใหม่เพื่อแก้ไข


1
มันขึ้นอยู่กับว่ามากและมักจะไม่
Maarten Bodewes

1

อาจมีสถานการณ์ต่าง ๆ ตามที่ผู้คนได้กล่าวถึงข้างต้น สองสิ่งที่ช่วยฉันแก้ไขปัญหานี้

  1. หากคุณใช้ IntelliJ

    File -> 'Invalidate Caches/Restart'

หรือ

  1. คลาสที่อ้างอิงอยู่ในโครงการอื่นและการอ้างอิงนั้นไม่ได้ถูกเพิ่มเข้าไปในไฟล์สร้างของ Gradle ของโครงการของฉัน ดังนั้นฉันจึงเพิ่มการพึ่งพาโดยใช้

    compile project(':anotherProject')

และมันก็ใช้งานได้ HTH!


1

คุณรวบรวมรหัสของคุณโดยใช้การรวบรวม Maven แล้วใช้การทดสอบ Maven เพื่อให้ทำงานได้ดี ตอนนี้ถ้าคุณเปลี่ยนบางสิ่งบางอย่างในรหัสของคุณแล้วโดยไม่ต้องคอมไพล์คุณกำลังเรียกใช้คุณจะได้รับข้อผิดพลาดนี้

การแก้ไข: รวบรวมอีกครั้งแล้วเรียกใช้การทดสอบ สำหรับฉันมันใช้วิธีนี้


1

ในกรณีของฉัน - ฉันต้องดำเนินการด้านล่าง:

  1. ย้ายcontext.xmlไฟล์จากsrc/java/packageไปยังresourceไดเรกทอรี (IntelliJ IDE)
  2. ทำความสะอาดtargetไดเรกทอรี

การย้ายไฟล์โดยไม่สนใจการอ้างอิงอาจทำให้เกิดข้อผิดพลาดนี้ ฉันได้พบสิ่งนี้แล้ว เพียงแค่รีเซ็ต Git และย้ายอย่างระมัดระวังอีกครั้งข้อผิดพลาดจะแก้ไข
Huy HómHỉnh

0

สำหรับคำแนะนำให้ดูที่ชื่อคลาสที่ใกล้จะเกิดข้อผิดพลาดและหมายเลขบรรทัดตัวอย่าง: Compilation failure [ERROR] \ applications \ xxxxx.java: ข้อผิดพลาด [44,30]: ไม่พบสัญลักษณ์

อีกสาเหตุหนึ่งที่ไม่สนับสนุนวิธีการสำหรับจาวาเวอร์ชันพูดว่า jdk7 vs 8 ตรวจสอบ% JAVA_HOME% ของคุณ


นี่แค่พูดในสิ่งเดียวกันกับที่คำตอบอื่นพูด
สตีเฟ่นซี
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.