"기호를 찾을 수 없음"또는 "기호를 해결할 수 없음"오류는 무엇을 의미합니까?

Sep 07 2014

"기호를 찾을 수 없음", "기호를 해결할 수 없음"또는 "기호를 찾을 수 없음"오류에 대해 다음을 설명하십시오.

  • 무슨 뜻입니까?
  • 원인은 무엇입니까?
  • 프로그래머는 어떻게 고칠까요?

이 질문은 Java의 이러한 일반적인 컴파일 오류에 대한 포괄적 인 Q & A를 제공하기 위해 고안되었습니다.

답변

441 StephenC Sep 07 2014 at 08:12

0. 두 오류간에 차이가 있습니까?

별로. "기호를 찾을 수 없음", "기호를 확인할 수 없음"및 "기호를 찾을 수 없음"은 모두 같은 의미입니다. 다른 Java 컴파일러는 다른 어법을 사용합니다.

1. "기호를 찾을 수 없음"오류는 무엇을 의미합니까?

첫째, 컴파일 오류 1 입니다. 그것은 것을 의미 중 하나를 자바 소스 코드에 문제가, 또는 당신이 그것을 컴파일하는 방식에 문제가있다.

Java 소스 코드는 다음과 같이 구성됩니다.

  • 키워드 : 같은 true, false, class, while, 등.
  • 리터럴 : 같은 42'X'"Hi mum!".
  • 연산자 및 기타 영숫자가 아닌 토큰 : 같은 +, =, {, 등.
  • 식별자 : 같은 Reader, i, toString, processEquibalancedElephants, 등.
  • 주석 및 공백.

"기호를 찾을 수 없음"오류는 식별자에 대한 것입니다. 코드가 컴파일 될 때 컴파일러는 코드의 모든 식별자가 무엇을 의미하는지 알아 내야합니다.

"기호를 찾을 수 없음"오류는 컴파일러가이를 수행 할 수 없음을 의미합니다. 코드가 컴파일러가 이해하지 못하는 것을 참조하는 것 같습니다.

2. "기호를 찾을 수 없음"오류의 원인은 무엇입니까?

첫 번째 순서로 원인은 하나뿐입니다. 컴파일러는 식별자 정의 해야하는 모든 위치를 조사했지만 정의를 찾을 수 없습니다. 이것은 여러 가지 원인으로 인해 발생할 수 있습니다. 일반적인 것은 다음과 같습니다.

  • 일반적인 식별자의 경우 :

    • 이름을 잘못 입력했을 수 있습니다. 즉 StringBiulder대신 StringBuilder. Java는 잘못된 철자 또는 입력 오류를 보상 할 수 없으며 보상하지 않을 것입니다.
    • 아마도 당신은 사건을 잘못 이해했을 것입니다. 즉 stringBuilder대신 StringBuilder. 모든 Java 식별자는 대소 문자를 구분합니다.
    • 아마도 밑줄을 부적절하게 사용했을 것입니다. 즉 mystringmy_string다릅니다. (자바 스타일 규칙을 고수하면이 실수로부터 대부분 보호받을 수 있습니다 ...)
    • 아마도 "다른 곳"으로 선언 된 것을 사용하려고 할 것입니다. 즉, 컴파일러에게 암시 적으로 보라고 말한 것과 다른 컨텍스트에서. (다른 클래스? 다른 범위? 다른 패키지? 다른 코드 기반?)
  • 변수를 참조해야하는 식별자의 경우 :

    • 아마도 변수 선언을 잊었을 것입니다.
    • 아마도 변수 선언은 사용하려고 한 시점에서 범위를 벗어났습니다. (아래 예 참조)
  • 메서드 또는 필드 이름이어야하는 식별자의 경우 :

    • 부모 / 상위 클래스 또는 인터페이스에서 선언되지 않은 상속 된 메서드 또는 필드를 참조하려고 할 수 있습니다.

    • 사용중인 유형에 존재하지 않는 (즉, 선언되지 않은) 메소드 또는 필드를 참조하려고 할 수 있습니다. 예 : "someString".push()2 .

    • 메서드를 필드로 사용하려고하거나 그 반대 일 수 있습니다. 예 : "someString".length또는 someArray.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진술과 몸. 에 대한 참조 iif문을 볼 수 의 선언 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루프, 그리고 따라서 이전 선언 ifor문이 범위를 벗어나 블록에.


다음은 오타로 인한 "기호를 찾을 수 없음"오류의 또 다른 예입니다.

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

이전의 선언에도 불구하고, tmptmp(...)표현은 잘못된 것입니다. 컴파일러는라는 메서드를 tmp찾고 찾을 수 없습니다. 이전에 선언 된 tmp것은 메서드의 네임 스페이스가 아니라 변수의 네임 스페이스에 있습니다.

내가 본 예에서 프로그래머는 실제로 연산자를 생략했습니다. 그가 쓴 의도는 다음과 같습니다.

int res = tmp * (a + b);

명령 줄에서 컴파일하는 경우 컴파일러가 기호를 찾지 못하는 또 다른 이유가 있습니다. 다른 클래스를 컴파일하거나 다시 컴파일하는 것을 잊었을 수도 있습니다. 예를 들어, 당신은 수업이 FooBar어디에서 Foo사용을 Bar. 컴파일 한 적이없고 Bar를 실행 javac Foo.java하면 컴파일러가 심볼을 찾을 수 없다는 것을 알 수 있습니다 Bar. 간단한 대답은 컴파일하는 것입니다 FooBar함께; 예 : 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. "수정"할 수있는 여러 가지 방법이 있습니다.

  • 나는 내부 forfor (int j = 1; j < 10; j++)-아마도 맞을 수 있습니다.
  • 내부 루프 또는 외부 루프 j 앞에 for 선언을 추가 할 수 있습니다 .forfor
  • 내가 바꿀 수 ji내부에서 for루프 - 잘못된 아마!
  • 등등.

요점은 당신이 있다는 것입니다 필요한 코드가 올바른 수정을 찾기 위해 어떻게 노력하고 이해하는.

4. 모호한 원인

자세히 살펴볼 때까지 "기호를 찾을 수 없음"이 설명 할 수없는 것처럼 보이는 몇 가지 경우가 있습니다.

  1. 잘못된 종속성 : 빌드 경로 및 프로젝트 종속성을 관리하는 IDE 또는 빌드 도구를 사용하는 경우 종속성에 실수를했을 수 있습니다. 예를 들어 종속성을 생략하거나 잘못된 버전을 선택했습니다. 빌드 도구 (Ant, Maven, Gradle 등)를 사용하는 경우 프로젝트의 빌드 파일을 확인하세요. IDE를 사용하는 경우 프로젝트의 빌드 경로 구성을 확인하십시오.

  2. 재 컴파일 하지 않습니다. 새로운 Java 프로그래머가 Java 도구 체인의 작동 방식을 이해하지 못하거나 반복 가능한 "빌드 프로세스"를 구현하지 않은 경우가 있습니다. 예를 들어 IDE, Ant, Maven, Gradle 등을 사용합니다. 이러한 상황에서 프로그래머는 코드를 제대로 재 컴파일하지 않아서 실제로 발생 하는 환상 오류를 찾기 위해 꼬리를 쫓아 가게 됩니다.

  3. 이전 빌드 문제 : 누락 된 클래스가있는 JAR 파일을 제공하는 방식으로 이전 빌드가 실패했을 수 있습니다. 이러한 실패는 일반적으로 빌드 도구를 사용하는 경우 알 수 있습니다. 그러나 다른 사람으로부터 JAR ​​파일을 얻는 경우 올바르게 빌드하고 오류를 발견 하는 데 의존 합니다. 의심되는 경우을 사용 tar -tvf하여 의심되는 JAR 파일의 내용을 나열하십시오.

  4. IDE 문제 : 사람들은 IDE가 혼동되고 IDE의 컴파일러가 존재하는 클래스를 찾을 수 없거나 그 반대의 상황을보고했습니다.

  • IDE가 잘못된 JDK 버전으로 구성된 경우 발생할 수 있습니다.

  • 이것은 IDE의 캐시가 파일 시스템과 동기화되지 않은 경우 발생할 수 있습니다. 이를 수정하는 IDE 특정 방법이 있습니다.

  • 이것은 IDE 버그 일 수 있습니다. 예를 들어 @Joel Costigliola는 Eclipse가 Maven "테스트"트리를 올바르게 처리하지 못하는 시나리오를 설명합니다. 이 답변을 참조하십시오 .

  1. Android 문제 : Android 용 으로 프로그래밍 할 때와 관련된 '기호를 찾을 수 없음'오류가 발생 R하면 R기호가 context.xml파일에 의해 정의 된다는 점에 유의하세요 . 당신 있는지 확인 context.xml파일이 정확하고 올바른 위치에 있고, 대응하는 R클래스 파일이 생성 된 / 컴파일. Java 기호는 대소 문자를 구분하므로 해당 XML ID도 대소 문자를 구분합니다.

    Android의 다른 기호 오류는 이전에 언급 한 이유 때문일 수 있습니다. 예 : 누락되거나 잘못된 종속성, 잘못된 패키지 이름, 특정 API 버전에없는 메서드 또는 필드, 맞춤법 / 입력 오류 등.

  2. 시스템 클래스 재정의 : 컴파일러 substring가 다음과 같이 알 수없는 기호 라고 불평하는 경우를 보았습니다.

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

    프로그래머가 자신의 버전을 만들었고 String그의 버전의 클래스는 substring메서드를 정의하지 않았다는 것이 밝혀졌습니다 .

    교훈 : 공용 라이브러리 클래스와 동일한 이름으로 자신의 클래스를 정의하지 마십시오!

  3. 호모 글리프 : 당신이 당신의 소스 파일을 UTF-8 인코딩을 사용하는 경우,이 식별자를 가질 수 있습니다 보면 같은, 그러나 호모 글리프 포함되어 있기 때문에 사실 다른에 있습니다. 자세한 내용은 이 페이지 를 참조하십시오.

    소스 파일 인코딩으로 자신을 ASCII 또는 Latin-1로 제한 \uxxxx하고 다른 문자에 대해 Java 이스케이프를 사용하여이를 방지 할 수 있습니다 .


1 - 경우, 아마, 당신은 다음 중 하나를 사용하면 컴파일 오류와 실행 코드로 IDE를 구성하거나 응용 프로그램이 실행시에 .. 생성하고 코드를 컴파일, 런타임 예외 또는 오류 메시지에이를 참조하십시오.

2-토목 공학의 세 가지 기본 원칙 : 물은 오르막으로 흐르지 않고, 판자는 측면이 더 강하며, 줄을 밀 수 없습니다 .

26 thinkterry Apr 17 2015 at 15:50

다음을 잊어 버린 경우에도이 오류가 발생합니다 new.

String s = String();

String s = new String();

포함하지 않는 전화 때문에 new키워드는 시도라는 (로컬) 방법을 찾을 것입니다 String인수없이 - 그 방법 서명 가능성이 정의되어 있지 않습니다.

14 Jan Dec 06 2015 at 16:19

'변수가 범위를 벗어남'의 또 다른 예

이미 그런 종류의 질문을 몇 번 봤 듯이 괜찮다고 느껴지 더라도 불법적 인 것에 대한 한 가지 더 예를들 수 있습니다 .

이 코드를 고려하십시오.

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

잘못된 코드입니다. 이름 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);
10 JoelCostigliola May 13 2016 at 17:09

Eclipse에서이 오류를 얻는 한 가지 방법 :

  1. 에서 클래스 A를 정의합니다 src/test/java.
  2. class 를 사용하는 다른 클래스 B를 정의하십시오 .src/main/javaA

결과 : Eclipse는 코드를 컴파일하지만 maven은 "Cannot find symbol"을 제공합니다.

기본 원인 : Eclipse는 기본 및 테스트 트리에 대해 결합 된 빌드 경로를 사용합니다. 불행히도 Eclipse 프로젝트의 다른 부분에 대해 다른 빌드 경로를 사용하는 것을 지원하지 않습니다. 이는 Maven이 요구하는 것입니다.

해결책 :

  1. 종속성을 그렇게 정의하지 마십시오. 즉,이 실수를하지 마십시오.
  2. Maven을 사용하여 코드베이스를 정기적으로 빌드하여이 실수를 조기에 발견하십시오. 이를 수행하는 한 가지 방법은 CI 서버를 사용하는 것입니다.
5 GT_hash Jun 30 2018 at 18:09

"찾을 수 없음"은 적절한 변수, 메서드, 클래스 등을 찾을 수없는 컴파일러를 의미합니다. 해당 오류 마사지를 받으면 먼저 오류 마사지를받을 코드 줄을 찾고자합니다. 사용하기 전에 정의하지 않은 변수, 메소드 또는 클래스를 찾을 수 있습니다. 확인 후 해당 변수, 메소드 또는 클래스를 나중에 필요에 사용할 수 있습니다 ... 다음 예제를 고려하십시오.

데모 클래스를 만들고 이름을 인쇄하겠습니다.

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);
      }
}

이제 새로운 출력을보십시오 ...

Ok 성공적으로 그 오류를 해결했습니다 .. 동시에, "can not find method"또는 "can not find class"무언가를 얻을 수 있다면, 처음에는 클래스 또는 메서드를 정의하고 사용 후 ..

3 JonathanLin Mar 08 2016 at 12:58

다른 곳에서 빌드에서이 오류가 발생하고 IDE에서 모든 것이 완벽하다고 말하면 두 위치에서 동일한 Java 버전을 사용하고 있는지 확인하십시오.

예를 들어 Java 7과 Java 8에는 서로 다른 API가 있으므로 이전 Java 버전에서 존재하지 않는 API를 호출하면이 오류가 발생합니다.

3 Ajay Oct 10 2019 at 19:07

해결

IntelliJ 사용

빌드 -> 프로젝트 다시 빌드를 선택 하면 문제가 해결됩니다.

2 DivyaJose Sep 28 2016 at 21:59

나도이 오류가 발생했습니다. (내가 검색하여이 페이지로 이동)

문제 : 다른 프로젝트 B에 정의 된 클래스에서 프로젝트 A의 클래스에 정의 된 정적 메서드를 호출했습니다. 다음 오류가 발생했습니다.

error: cannot find symbol

솔루션 : 먼저 메서드가 정의 된 프로젝트를 빌드 한 다음 메서드가 호출 된 프로젝트를 빌드하여이 문제를 해결했습니다.

2 UdayKiranPulipati Jan 24 2019 at 18:18

Eclipse Java 빌드 경로가 7, 8에 매핑되고 프로젝트 pom.xml Maven 속성에서 java.version이 7,8보다 높은 Java 버전 (9,10,11 등)으로 언급 된 경우 pom에서 업데이트해야합니다. xml 파일.

Eclipse에서 Java가 Java 버전 11에 매핑되고 pom.xml에서 Java 버전 8에 매핑됩니다. Eclipse IDE 도움말-> 새 소프트웨어 설치-> 아래 단계를 수행하여 Eclipse 지원을 Java 11로 업데이트합니다.

다음 링크를 붙여 넣으십시오. http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With

또는

추가 (팝업 창이 열립니다)->

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

그런 다음 아래와 같이 pom.xml 파일 의 Maven 속성에서 Java 버전을 업데이트 하십시오.

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

마지막으로 프로젝트 Debug as-> Maven clean, Maven 빌드 단계를 마우스 오른쪽 버튼으로 클릭하십시오.

1 avp Aug 18 2018 at 08:45

사람들이 위에서 언급했듯이 다양한 시나리오가있을 수 있습니다. 이 문제를 해결하는 데 도움이 된 몇 가지.

  1. IntelliJ를 사용하는 경우

    File -> 'Invalidate Caches/Restart'

또는

  1. 참조되는 클래스가 다른 프로젝트에 있었고 해당 종속성이 내 프로젝트의 Gradle 빌드 파일에 추가되지 않았습니다. 그래서 나는

    compile project(':anotherProject')

그리고 그것은 작동했습니다. HTH!

1 ANILKUMAR Aug 07 2019 at 11:59

Maven 컴파일을 사용하여 코드를 컴파일 한 다음 Maven 테스트를 사용하여 제대로 작동했습니다. 이제 코드에서 무언가를 변경 한 다음 컴파일하지 않고 실행하면이 오류가 발생합니다.

솔루션 : 다시 컴파일하고 테스트를 실행하십시오. 나를 위해 그것은 이런 식으로 작동했습니다.

1 VIPINKUMAR Sep 08 2019 at 14:50

제 경우에는 아래 작업을 수행해야했습니다.

  1. 이동 context.xml에서 파일을 src/java/package받는 resource디렉토리 (인 IntelliJ IDE)
  2. 깨끗한 target디렉토리.
Striker Sep 06 2017 at 19:47

힌트를 보려면 오류를 발생시키는 클래스 이름 이름과 줄 번호를 자세히 살펴보십시오. 예 : 컴파일 실패 [ERROR] \ applications \ xxxxx.java : [44,30] 오류 : 기호를 찾을 수 없음

다른 원인 중 하나는 Java 버전에 대해 지원되지 않는 방법으로 jdk7 대 8입니다. % JAVA_HOME %을 확인하십시오.

sakra Jul 20 2020 at 19:31

Gradle 다중 프로젝트 빌드로 설정된 Java 프로젝트에서 오류가 발생했습니다. 하위 프로젝트 중 하나에 Gradle Java Library 플러그인 이없는 것으로 나타났습니다 . 이로 인해 하위 프로젝트의 클래스 파일이 빌드의 다른 프로젝트에 표시되지 않았습니다.

build.gradle다음과 같은 방법으로 Java 라이브러리 플러그인을 하위 프로젝트에 추가 한 후 오류가 사라졌습니다.

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

이 오류를 이렇게 해결했습니다 ... 안드로이드의 광기. 패키지 이름을 Adapter로 사용하고 "A"대신 "a"를 사용하여 이름을 어댑터로 리팩터링하고 오류를 해결했습니다.