O que significa um erro "Não é possível encontrar o símbolo" ou "Não é possível resolver o símbolo"?

395

Explique o seguinte sobre os erros "Não é possível encontrar o símbolo" e "Não é possível resolver o símbolo":

  • O que eles querem dizer?
  • O que as coisas podem causar?
  • Como o programador os corrige?

Esta pergunta foi criada para propagar uma Q&A abrangente sobre esses erros comuns de compilação em Java.

Stephen C
fonte

Respostas:

417

0. Existe alguma diferença entre os dois erros?

Na verdade não. "Não é possível encontrar o símbolo" e "Não é possível resolver o símbolo" significam a mesma coisa. Alguns compiladores Java usam uma frase e outros a outra.

1. O que significa um erro "Não é possível encontrar o símbolo"?

Em primeiro lugar, é um erro de compilação 1 . Isso significa que tanto há um problema em seu código-fonte Java, ou há um problema na maneira que você está compilando-lo.

Seu código-fonte Java consiste no seguinte:

  • Palavras-chave: como true, false, class, while, e assim por diante.
  • Literais: como 42e 'X'e "Hi mum!".
  • Operadores e outros símbolos não alfanuméricos: como +, =, {e assim por diante.
  • Identificadores: como Reader, i, toString, processEquibalancedElephants, e assim por diante.
  • Comentários e espaço em branco.

Um erro "Não é possível encontrar o símbolo" é sobre os identificadores. Quando seu código é compilado, o compilador precisa descobrir o que significa cada identificador no seu código.

Um erro "Não é possível encontrar o símbolo" significa que o compilador não pode fazer isso. Seu código parece estar se referindo a algo que o compilador não entende.

2. O que pode causar um erro "Não é possível encontrar o símbolo"?

Como primeira ordem, há apenas uma causa. O compilador procurou em todos os lugares onde o identificador deveria ser definido e não conseguiu encontrar a definição. Isso pode ser causado por várias coisas. Os mais comuns são os seguintes:

  • Para identificadores em geral:
    • Talvez você tenha soletrado o nome incorretamente; ou seja, em StringBiuldervez de StringBuilder. Java não pode e não tentará compensar erros ortográficos ou de digitação incorretos.
    • Talvez você tenha entendido errado o caso; ou seja, em stringBuildervez de StringBuilder. Todos os identificadores Java diferenciam maiúsculas de minúsculas.
    • Talvez você tenha usado sublinhados inadequadamente; ou seja, mystringe my_stringsão diferentes. (Se você seguir as regras do estilo Java, estará amplamente protegido contra esse erro ...)
    • Talvez você esteja tentando usar algo que foi declarado "em outro lugar"; ou seja, em um contexto diferente daquele em que você implicitamente disse ao compilador para procurar. (Uma classe diferente? Um escopo diferente? Um pacote diferente? Uma base de código diferente?)
  • Para identificadores que devem se referir a variáveis:
    • Talvez você tenha esquecido de declarar a variável.
    • Talvez a declaração da variável esteja fora do escopo no ponto em que você tentou usá-la. (Veja o exemplo abaixo)
  • Para identificadores que devem ser nomes de métodos ou campos:

    • Talvez você esteja tentando se referir a um método ou campo herdado que não foi declarado nas interfaces ou classes pai / ancestral.
    • Talvez você esteja tentando se referir a um método ou campo que não existe (ou seja, não foi declarado) no tipo que você está usando; por exemplo "someString".push()2 .
    • Talvez você esteja tentando usar um método como um campo ou vice-versa; por exemplo "someString".lengthou someArray.length().
    • Talvez você esteja operando por engano em uma matriz em vez de em um elemento da matriz; por exemplo

      String strings[] = ...
      if (strings.charAt(3)) { ... }
      // maybe that should be 'strings[0].charAt(3)'
      
  • Para identificadores que devem ser nomes de classe:

    • Talvez você tenha esquecido de importar a classe.
    • Talvez você tenha usado importações "estrela", mas a classe não está definida em nenhum dos pacotes importados.
    • Talvez você tenha esquecido um newcomo em:

      String s = String();  // should be 'new String()'
  • Para casos em que o tipo ou instância não parece ter o membro que você esperava:

    • Talvez você tenha declarado uma classe aninhada ou um parâmetro genérico que oculta o tipo que você pretendia usar.
    • Talvez você esteja sombreando uma variável estática ou de instância.
    • Talvez você tenha importado o tipo errado; por exemplo, devido à conclusão ou correção automática do IDE.
    • Talvez você esteja usando (compilando) a versão errada de uma API.
    • Talvez você tenha esquecido de lançar seu objeto em uma subclasse apropriada.

O problema geralmente é uma combinação dos itens acima. Por exemplo, talvez você "tenha estrela" importado java.io.*e depois tentou usar a Filesclasse ... que java.nionão está java.io. Ou talvez você pretendesse escrever File... que é uma aula java.io.


Aqui está um exemplo de como o escopo variável incorreto pode levar a um erro "Não é possível encontrar o símbolo":

List<String> strings = ...

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

Isso fornecerá um erro "Não é possível encontrar o símbolo" ina ifinstrução. Embora tenhamos declarado anteriormente i, essa declaração está apenas no escopo da fordeclaração e de seu corpo. A referência a ina ifdeclaração não pode ver essa declaração de i. Está fora do escopo .

(Uma correção apropriada aqui pode ser mover a ifinstrução para dentro do loop ou declarar iantes do início do loop.)


Aqui está um exemplo que causa perplexidade em que um erro de digitação leva a um erro aparentemente inexplicável "Não é possível encontrar o símbolo":

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

Isso gerará um erro de compilação na printlnchamada dizendo que inão pode ser encontrado. Mas (eu ouvi você dizer) eu declarei!

O problema é o ponto e vírgula furtivo ( ;) antes do {. A sintaxe da linguagem Java define um ponto-e-vírgula nesse contexto como uma instrução vazia . A declaração vazia se torna o corpo do forloop. Portanto, esse código realmente significa isso:

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

// The previous and following are separate statements!!

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

O { ... }bloco não é o corpo do forloop, e, portanto, a declaração anterior de ina fordeclaração é fora do escopo no bloco.


Aqui está outro exemplo de erro "Não é possível encontrar o símbolo" causado por um erro de digitação.

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

Apesar da declaração anterior, tmpa tmp(...)expressão está incorreta. O compilador procurará um método chamado tmpe não o encontrará. O declarado anteriormente tmpestá no espaço de nomes para variáveis, não no espaço de nomes para métodos.

No exemplo que me deparei, o programador havia deixado de fora um operador. O que ele pretendia escrever era o seguinte:

int res = tmp * (a + b);

Há outra razão pela qual o compilador pode não encontrar um símbolo se você estiver compilando na linha de comando. Você pode simplesmente ter esquecido de compilar ou recompilar alguma outra classe. Por exemplo, se você tem classes Fooe Baronde Foousa Bar. Se você nunca compilou Bare executou javac Foo.java, é provável que descubra que o compilador não pode encontrar o símbolo Bar. A resposta simples é compilar Fooe Barjuntos; por exemplo javac Foo.java Bar.javaou javac *.java. Ou melhor ainda, use uma ferramenta de construção Java; por exemplo, Ant, Maven, Gradle e assim por diante.

Existem outras causas mais obscuras também ... com as quais tratarei abaixo.

3. Como faço para corrigir esses erros?

De um modo geral, você começa descobrindo o que causou o erro de compilação.

  • Veja a linha no arquivo indicado pela mensagem de erro de compilação.
  • Identifique qual símbolo está falando da mensagem de erro.
  • Descubra por que o compilador está dizendo que não consegue encontrar o símbolo; Veja acima!

Então você pensa sobre o que seu código deveria estar dizendo. Finalmente, você decide a correção que precisa fazer no seu código-fonte para fazer o que deseja.

Observe que nem todas as "correções" estão corretas. Considere isto:

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

Suponha que o compilador diga "Não é possível encontrar o símbolo" para j. Há muitas maneiras de eu "consertar" isso:

  • Eu poderia mudar o interior forpara for (int j = 1; j < 10; j++)- provavelmente correto.
  • Eu poderia adicionar uma declaração j antes do forloop interno ou externo for- possivelmente correto.
  • Eu poderia mudar jpara ino forloop interno - provavelmente errado!
  • e assim por diante.

O ponto é que você precisa entender o que seu código está tentando fazer para encontrar a correção correta.

4. Causas obscuras

Aqui estão alguns casos em que o "Não é possível encontrar o símbolo" é aparentemente inexplicável ... até você olhar mais de perto.

  1. Dependências incorretas : se você estiver usando um IDE ou uma ferramenta de construção que gerencia o caminho de construção e as dependências do projeto, pode ter cometido um erro com as dependências; por exemplo, deixou de fora uma dependência ou selecionou a versão errada. Se você estiver usando uma ferramenta de construção (Ant, Maven, Gradle, etc.), verifique o arquivo de construção do projeto. Se você estiver usando um IDE, verifique a configuração do caminho de construção do projeto.

  2. Você não está recompilando : às vezes acontece que novos programadores Java não entendem como a cadeia de ferramentas Java funciona ou não implementaram um "processo de construção" repetível; por exemplo, usando um IDE, Ant, Maven, Gradle e assim por diante. Em tal situação, o programador pode acabar perseguindo seu rabo procurando um erro ilusório que é realmente causado por não recompilar o código corretamente, e coisas do tipo ...

  3. Um problema de construção anterior : é possível que uma construção anterior tenha falhado de uma maneira que forneceu um arquivo JAR com classes ausentes. Essa falha normalmente seria notada se você estivesse usando uma ferramenta de construção. No entanto, se você está recebendo arquivos JAR de outra pessoa, você é dependente de lhes construir corretamente, e percebendo erros. Se você suspeitar disso, use tar -tvfpara listar o conteúdo do arquivo JAR suspeito.

  4. Problemas com o IDE : as pessoas relataram casos em que o IDE fica confuso e o compilador no IDE não consegue encontrar uma classe que existe ... ou a situação inversa.

    • Isso pode acontecer se o IDE tiver sido configurado com a versão errada do JDK.

    • Isso pode acontecer se os caches do IDE ficarem fora de sincronia com o sistema de arquivos. Existem maneiras específicas de IDE para corrigir isso.

    • Isso pode ser um bug do IDE. Por exemplo, @Joel Costigliola descreve um cenário em que o Eclipse não manipula uma árvore de "teste" do Maven corretamente: consulte esta resposta .

  5. Problemas com o Android : quando você estiver programando para o Android e tiver erros relacionados a "Não é possível encontrar o símbolo" R, lembre-se de que os Rsímbolos são definidos pelo context.xmlarquivo. Verifique se o seu context.xmlarquivo está correto e no lugar correto, e se o Rarquivo de classe correspondente foi gerado / compilado. Observe que os símbolos Java diferenciam maiúsculas de minúsculas, portanto, os IDs XML correspondentes também diferenciam maiúsculas de minúsculas.

    É provável que outros erros de símbolo no Android sejam causados ​​por razões de menção anterior; por exemplo, dependências ausentes ou incorretas, nomes de pacotes incorretos, métodos ou campos que não existem em uma versão específica da API, erros de ortografia / digitação e assim por diante.

  6. Redefinindo classes de sistema : eu vi casos em que o compilador reclama que substringé um símbolo desconhecido em algo como o seguinte

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

    Descobriu-se que o programador havia criado sua própria versão Stringe que sua versão da classe não definia um substringmétodo.

    Lição: não defina suas próprias classes com os mesmos nomes que as classes comuns da biblioteca!

  7. Homoglyphs: Se você usar a codificação UTF-8 para seus arquivos de origem, é possível ter identificadores com a mesma aparência , mas são de fato diferentes porque contêm homoglyphs. Veja esta página para mais informações.

    Você pode evitar isso restringindo-se a ASCII ou Latin-1 como a codificação do arquivo de origem e usando \uxxxxescapes de Java para outros caracteres.


1 - Se, por acaso, você não vê isso em uma exceção de tempo de execução ou mensagem de erro, então ou você configurou o IDE para executar código com erros de compilação, ou seu aplicativo está gerando e compilar o código .. em tempo de execução.

2 - Os três princípios básicos da Engenharia Civil: a água não flui para cima, uma prancha é mais forte de lado e você não pode empurrar uma corda .

Stephen C
fonte
Eu tive outra situação em que esse erro de compilação ocorreu enquanto o eclipse não via o problema: Duas classes com dependências definidas na outra classe, respectivamente. No meu caso, eu tinha um enum, implementando uma interface, definida em uma classe em que eu tolo já usava o enum.
Jogi 23/05
De maneira semelhante ao comentário acima, quando eu compilar e executar meu programa no Eclipse, ele não funcionará. A compilação a partir do console gera vários desses erros "Não é possível encontrar o símbolo", geralmente relacionados ao último elemento de uma importação. Não tenho ideia do que está causando isso, pois não há realmente nada errado no código.
Andres Stadelmann 27/05
Outro problema é que os IDEs podem "interpretar" outros erros nessa categoria. Por exemplo println, System.out.printlnse colocado no nível da classe no compilador padrão nos daria <identifier> expected( demo ), mas no IntelliJ veremos Cannot resolve symbol 'println'( demo ).
Pshemo 14/11/19
Uau. Eu chamaria isso de bug do compilador.
Stephen C
23

Você também receberá esse erro se esquecer de new:

String s = String();

versus

String s = new String();

porque a chamada sem a newpalavra - chave tentará procurar um método (local) chamado Stringsem argumentos - e essa assinatura do método provavelmente não está definida.

pensador
fonte
14

Mais um exemplo de 'Variável está fora do escopo'

Como já vi esse tipo de perguntas algumas vezes, talvez mais um exemplo do que é ilegal, mesmo que possa parecer bom.

Considere este código:

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

Esse código é inválido. Como nenhuma das variáveis ​​nomeadas messageé visível fora do respectivo escopo - quais seriam os colchetes {}nesse caso.

Você pode dizer: "Mas uma variável chamada mensagem é definida de qualquer maneira - portanto, a mensagem é definida após o if".

Mas você estaria errado.

O Java não possui operadores free()ou delete, portanto, ele deve confiar no rastreamento do escopo da variável para descobrir quando as variáveis ​​não são mais usadas (junto com as referências a essas variáveis ​​de causa).

É especialmente ruim se você pensou que fez algo de bom. Eu vi esse tipo de erro depois de "otimizar" o código assim:

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

"Oh, há código duplicado, vamos puxar essa linha comum" -> e aí está.

A maneira mais comum de lidar com esse tipo de problema de escopo seria atribuir previamente os valores else aos nomes de variáveis ​​no escopo externo e, em seguida, reatribuir se:

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);
Jan
fonte
4
"O Java não possui operadores free () ou delete, portanto, ele depende do rastreamento do escopo da variável para descobrir quando as variáveis ​​não são mais usadas (junto com as referências a essas variáveis ​​de causa)." - Embora seja verdade, isso não é relevante. C e C ++ têm operadores de exclusão / exclusão, respectivamente, e ainda assim o código C / C ++ equivalente aos seus exemplos seria ilegal. Os blocos C e C ++ limitam o escopo das variáveis, como em Java. De fato, isso é verdade para a maioria das linguagens "estruturadas em bloco".
Stephen C
11
A melhor solução para o código que atribui um valor diferente em cada ramificação é usar uma declaração de variável em brancofinal .
Daniel Pryden
10

Uma maneira de obter esse erro no Eclipse:

  1. Defina uma classe Aem src/test/java.
  2. Definir outra classe Bem src/main/javaque a classe usos A.

Resultado: o Eclipse compilará o código, mas o maven fornecerá "Não é possível encontrar o símbolo".

Causa subjacente: O Eclipse está usando um caminho de construção combinado para as árvores principal e de teste. Infelizmente, ele não suporta o uso de caminhos de construção diferentes para diferentes partes de um projeto Eclipse, que é o que o Maven exige.

Solução:

  1. Não defina suas dependências dessa maneira; ou seja, não cometa esse erro.
  2. Crie regularmente sua base de código usando o Maven, para que você considere esse erro mais cedo. Uma maneira de fazer isso é usar um servidor de IC.
Joel Costigliola
fonte
Qual é a solução para este?
2
tudo o que você usa em src / main / java precisa ser definido em src / main / java ou em qualquer dependência de compilação / tempo de execução (não dependências de teste).
Joel Costigliola
5

"Não é possível encontrar" significa que, o compilador que não consegue encontrar a variável, método, classe, etc. apropriados ... se você recebeu a massagem com erro, antes de mais nada, deseja encontrar a linha de código onde recebe a massagem com erro ... E então você capaz de encontrar qual variável, método ou classe não definiu antes de usá-lo. Após a confirmação inicializar essa variável, método ou classe pode ser usado para requerer mais tarde ... Considere o seguinte exemplo.

Vou criar uma aula de demonstração e imprimir um nome ...

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

Agora veja o resultado ..

insira a descrição da imagem aqui

Esse erro diz: "o nome da variável não pode encontrar". A definição e a inicialização do valor da variável 'name' podem ser abolidas nesse erro. Na verdade, dessa forma,

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

             String name="smith";

             System.out.print(name);
      }
}

Agora veja a nova saída ...

insira a descrição da imagem aqui

Ok Resolvido com êxito esse erro .. Ao mesmo tempo, se você pudesse obter algo "não é possível encontrar o método" ou "não é possível encontrar a classe", primeiro defina uma classe ou método e depois use-o ..

GT_hash
fonte
3

Se você estiver recebendo esse erro na compilação em outro lugar, enquanto o IDE diz que tudo está perfeitamente bem, verifique se você está usando as mesmas versões do Java nos dois lugares.

Por exemplo, Java 7 e Java 8 têm APIs diferentes, portanto, chamar uma API inexistente em uma versão Java mais antiga causaria esse erro.

Jonathan Lin
fonte
2

Eu também estava recebendo esse erro. (pelo qual pesquisei no Google e fui direcionado para esta página)

Problema: eu estava chamando um método estático definido na classe de um projeto A de uma classe definida em outro projeto B. Eu estava recebendo o seguinte erro:

error: cannot find symbol

Solução: resolvi isso criando primeiro o projeto em que o método está definido e depois o projeto de onde o método estava sendo chamado.

Divya Jose
fonte
Sim, isso pode acontecer se você decidir mover alguma função reutilizável do seu pacote atual para o seu pacote de utilitários comuns, por exemplo, mas depois esquecer de compilar seu pacote comum antes de chamar a função do seu pacote atual.
buildingKofi
2

Se o caminho de construção do eclipse Java estiver mapeado para 7, 8 e nas propriedades do Projeto pom.xml Maven, java.version será mencionada na versão Java superior (9,10,11, etc.) que 7,8, você precisará atualizar no pom. arquivo xml.

No Eclipse, se o Java estiver mapeado para o Java versão 11 e no pom.xml, ele será mapeado para o Java versão 8. Atualize o suporte do Eclipse para o Java 11 seguindo as etapas abaixo na Ajuda do eclipse IDE -> Instalar novo software ->

Cole o link a seguir http://download.eclipse.org/eclipse/updates/4.9-P-builds em trabalho com

ou

Adicionar (a janela pop-up será aberta) ->

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

atualize a versão Java nas propriedades do Maven do arquivo pom.xml, conforme abaixo

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

Por fim, clique com o botão direito do mouse no projeto Debug como -> Maven clean, Maven build steps

UdayKiran Pulipati
fonte
2

RESOLVIDO

Selecione Build -> Rebuild Project irá resolvê-lo

Ajay
fonte
11
Isso depende muito e geralmente não.
Maarten Bodewes
1

Pode haver vários cenários, como as pessoas mencionaram acima. Algumas coisas que me ajudaram a resolver isso.

  1. Se você estiver usando o IntelliJ

    File -> 'Invalidate Caches/Restart'

OU

  1. A classe que está sendo referenciada estava em outro projeto e essa dependência não foi adicionada ao arquivo de construção Gradle do meu projeto. Então eu adicionei a dependência usando

    compile project(':anotherProject')

e funcionou. HTH!

avp
fonte
1

você compilou seu código usando o maven compile e depois usou o maven test para executá-lo funcionou bem. Agora, se você alterou algo no seu código e, em seguida, sem compilá-lo, você receberá esse erro.

Solução: Compile novamente e execute o teste. Para mim, funcionou dessa maneira.

ANIL KUMAR
fonte
1

No meu caso - tive que executar as operações abaixo:

  1. Mover context.xmlarquivo de src/java/packagepara o resourcediretório (IntelliJ IDE)
  2. targetDiretório limpo .
VIPIN KUMAR
fonte
Mover arquivo sem se preocupar com referências pode causar esse erro. Eu já conheci isso. Apenas redefina no Git e mova-o com cuidado novamente, o erro foi solucionado.
Huy Hóm Hỉnh 2/10/19
0

Para obter dicas, olhe mais de perto o nome do nome da classe que gera um erro e o número da linha, exemplo: Falha na compilação [ERRO] \ applications \ xxxxx.java: [44,30] erro: não é possível encontrar o símbolo

Uma outra causa é o método não suportado da versão java, digamos jdk7 vs 8. Verifique seu% JAVA_HOME%

atacante
fonte
Isso apenas diz a mesma coisa que outras respostas dizem.
Stephen C