O que significa um erro “Não é possível encontrar o símbolo” ou “Não é possível resolver o símbolo”?
Explique o seguinte sobre os erros "Não é possível encontrar o símbolo", "Não é possível resolver o símbolo" ou "Símbolo não encontrado":
- O que eles querem dizer?
- O que as coisas podem causar?
- Como o programador os corrige?
Esta pergunta foi projetada para semear um Q&A abrangente sobre esses erros comuns de compilação em Java.
Respostas
0. Existe alguma diferença entre os dois erros?
Na verdade não. "Não é possível encontrar o símbolo", "Não é possível resolver o símbolo" e "Símbolo não encontrado" significam a mesma coisa. Diferentes compiladores Java usam fraseologia diferente.
1. O que significa o 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
42
e'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 em 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, existe 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 uma série de coisas. Os mais comuns são os seguintes:
Para identificadores em geral:
- Talvez você tenha soletrado o nome incorretamente; ou seja, em
StringBiulder
vez deStringBuilder
. Java não pode e não tentará compensar erros ortográficos ou de digitação. - Talvez você tenha entendido errado o caso; ou seja, em
stringBuilder
vez deStringBuilder
. Todos os identificadores Java são sensíveis a maiúsculas e minúsculas. - Talvez você tenha usado sublinhados de forma inadequada; ou seja,
mystring
emy_string
são diferentes. (Se você seguir as regras de estilo Java, estará amplamente protegido contra esse erro ...) - Talvez você esteja tentando usar algo que foi declarado "em outro lugar"; isto é, em um contexto diferente de onde você disse implicitamente ao compilador para olhar. (Uma classe diferente? Um escopo diferente? Um pacote diferente? Uma base de código diferente?)
- Talvez você tenha soletrado o nome incorretamente; ou seja, em
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 classes ou interfaces 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 está usando; por exemplo,
"someString".push()
2 .Talvez você esteja tentando usar um método como um campo, ou vice-versa; por exemplo
"someString".length
ousomeArray.length()
.Talvez você esteja operando erroneamente em uma matriz em vez de um elemento de 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 que você importou.
Talvez você tenha esquecido um
new
como 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 obscurece o tipo que você pretendia usar.
- Talvez você esteja ocultando uma variável estática ou de instância.
- Talvez você importou o tipo errado; por exemplo, devido à conclusão do IDE ou correção automática.
- 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 importado com "estrela" java.io.*
e depois tentado usar a Files
classe ... que java.nio
não está java.io
. Ou talvez você quisesse escrever File
... que é uma classe em java.io
.
Aqui está um exemplo de como o escopo de 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 gerará um erro "Não é possível encontrar o símbolo" i
na if
instrução. Embora tenhamos declarado anteriormente i
, essa declaração está apenas no escopo da for
instrução e seu corpo. A referência a i
na if
declaração não pode ver essa declaração de i
. Está fora do escopo .
(Uma correção apropriada aqui pode ser mover a if
instrução dentro do loop ou declarar i
antes do início do loop.)
Aqui está um exemplo que causa confusão 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 println
chamada dizendo que i
não foi encontrado. Mas (eu ouço você dizer) eu declarei isso!
O problema é o ponto-e-vírgula sorrateiro ( ;
) antes de {
. A sintaxe da linguagem Java define um ponto-e-vírgula nesse contexto como uma instrução vazia . A instrução vazia então se torna o corpo do for
loop. Então, 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 for
loop e, portanto, a declaração anterior de i
na for
instrução está fora do escopo do bloco.
Aqui está outro exemplo de erro "Não é possível localizar o símbolo" causado por um erro de digitação.
int tmp = ...
int res = tmp(a + b);
Apesar da declaração anterior, o tmp
na tmp(...)
expressão está incorreto. O compilador procurará um método chamado tmp
e não encontrará nenhum. O declarado anteriormente tmp
está no namespace para variáveis, não no namespace para métodos.
No exemplo que encontrei, o programador havia realmente omitido um operador. O que ele pretendia escrever era o seguinte:
int res = tmp * (a + b);
Há outro motivo pelo qual o compilador pode não encontrar um símbolo se você estiver compilando a partir da linha de comando. Você pode simplesmente ter esquecido de compilar ou recompilar alguma outra classe. Por exemplo, se você tem aulas Foo
e Bar
onde Foo
usa Bar
. Se você nunca compilou Bar
e o executa javac Foo.java
, é provável que descubra que o compilador não consegue encontrar o símbolo Bar
. A resposta simples é compilar Foo
e Bar
juntar; por exemplo javac Foo.java Bar.java
ou javac *.java
. Ou melhor ainda, use uma ferramenta de construção Java; por exemplo, Ant, Maven, Gradle e assim por diante.
Existem algumas outras causas mais obscuras também ... das quais tratarei a seguir.
3. Como faço para corrigir esses erros?
De modo geral, você começa descobrindo o que causou o erro de compilação.
- Observe a linha no arquivo indicada pela mensagem de erro de compilação.
- Identifique de qual símbolo a mensagem de erro está falando.
- 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. Então, finalmente, você calcula que correção precisa fazer no código-fonte para fazer o que deseja.
Observe que nem todas as "correções" sã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 "consertar" isso:
- Eu poderia mudar o interno
for
parafor (int j = 1; j < 10; j++)
- provavelmente correto. - Eu poderia adicionar uma declaração para
j
antes dofor
loop interno ou dofor
loop externo - possivelmente correto. - Eu poderia mudar
j
parai
nofor
loop 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 certa.
4. Causas obscuras
Aqui estão alguns casos em que o "Símbolo não encontrado" é aparentemente inexplicável ... até que você olhe mais de perto.
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, omitiu 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.
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 o próprio rabo à procura de um erro ilusório que é realmente causado por não recompilar o código corretamente e assim por diante ...
Um problema de construção anterior : é possível que uma construção anterior tenha falhado de uma forma que forneceu um arquivo JAR com classes ausentes. Normalmente, essa falha seria observada se você estivesse usando uma ferramenta de construção. No entanto, se estiver obtendo arquivos JAR de outra pessoa, você dependerá da construção adequada deles e da detecção de erros. Se você suspeitar disso, use
tar -tvf
para listar o conteúdo do arquivo JAR suspeito.Problemas de IDE : as pessoas relataram casos em que seu IDE fica confuso e o compilador no IDE não consegue encontrar uma classe existente ... 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 consertar isso.
Isso pode ser um bug do IDE. Por exemplo, @Joel Costigliola descreve um cenário onde o Eclipse não lida com uma árvore de "teste" Maven corretamente: veja esta resposta .
Problemas do Android : quando você estiver programando para Android e tiver erros "Não é possível encontrar o símbolo" relacionados
R
, esteja ciente de que osR
símbolos são definidos pelocontext.xml
arquivo. Verifique se o seucontext.xml
arquivo está correto e no lugar correto e se oR
arquivo 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.Outros erros de símbolo no Android são provavelmente devido a motivos mencionados anteriormente; por exemplo, dependências ausentes ou incorretas, nomes de pacotes incorretos, métodos ou campos que não existem em uma determinada versão da API, erros de ortografia / digitação e assim por diante.
Redefinindo classes de sistema : vi casos em que o compilador reclama que
substring
é um símbolo desconhecido em algo como o seguinteString s = ... String s1 = s.substring(1);
Descobriu-se que o programador havia criado sua própria versão de
String
e que sua versão da classe não definiasubstring
métodos.Lição: Não defina suas próprias classes com os mesmos nomes das classes de biblioteca comuns!
Homóglifos: se você usar a codificação UTF-8 para seus arquivos de origem, é possível ter identificadores que parecem iguais, mas são na verdade diferentes porque contêm homóglifos. 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
\uxxxx
escapes 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 sobe, uma prancha é mais forte do lado e não se pode empurrar um fio .
Você também receberá este erro se esquecer new
:
String s = String();
versus
String s = new String();
porque a chamada sem a new
palavra - chave tentará procurar um método (local) chamado String
sem argumentos - e essa assinatura de método provavelmente não está definida.
Mais um exemplo de 'Variável fora do escopo'
Como já vi esse tipo de pergunta algumas vezes, talvez mais um exemplo do que é ilegal, mesmo que pareça correto.
Considere este código:
if(somethingIsTrue()) {
String message = "Everything is fine";
} else {
String message = "We have an error";
}
System.out.println(message);
Este é um código inválido. Porque nenhuma das variáveis nomeadas message
é visível fora de seu respectivo escopo - que seriam os colchetes {}
neste caso.
Você pode dizer: "Mas uma variável chamada mensagem é definida de qualquer maneira - então a mensagem é definida após if
".
Mas você estaria errado.
Java não tem operadores free()
ou delete
, portanto, ele precisa contar com o 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 bom. Já vi esse tipo de erro depois de "otimizar" o código como este:
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 pronto.
A maneira mais comum de lidar com esse tipo de problema de escopo seria pré-atribuir os valores else aos nomes de variáveis no escopo externo e então reatribuir se:
String message = "We have an error";
if(somethingIsTrue()) {
message = "Everything is fine";
}
System.out.println(message);
Uma maneira de obter esse erro no Eclipse:
- Defina uma classe
A
emsrc/test/java
. - Defina outra classe
B
emsrc/main/java
que usa classeA
.
Resultado: o Eclipse irá compilar o código, mas o maven fornecerá "Não é possível encontrar o símbolo".
Causa subjacente: Eclipse está usando um caminho de construção combinado para as árvores principal e de teste. Infelizmente, ele não suporta o uso de diferentes caminhos de construção para diferentes partes de um projeto Eclipse, que é o que o Maven requer.
Solução:
- Não defina suas dependências dessa maneira; ou seja, não cometa esse erro.
- Crie regularmente sua base de código usando Maven para que você descubra esse erro antes do tempo. Uma maneira de fazer isso é usar um servidor de CI.
"Não é possível encontrar" significa que, compilador que não consegue encontrar a variável apropriada, método, classe etc ... se você recebeu aquela massagem de erro, primeiro de tudo você deseja encontrar a linha de código onde obter a massagem de erro ... E então você irá 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 exigir posteriormente ... Considere o seguinte exemplo.
Vou criar uma classe de demonstração e imprimir um nome ...
class demo{
public static void main(String a[]){
System.out.print(name);
}
}
Agora veja o resultado ..
Esse erro diz, "o nome da variável não pode ser encontrado" .. Definir e inicializar o valor para a variável 'nome' pode ser abolido esse erro .. Na verdade assim,
class demo{
public static void main(String a[]){
String name="smith";
System.out.print(name);
}
}
Agora olhe para a nova saída ...
Ok, resolvido com sucesso esse erro .. Ao mesmo tempo, se você pudesse obter "não consigo encontrar método" ou "não consigo encontrar classe" algo, primeiro defina uma classe ou método e depois use isso ..
Se você está recebendo este erro na construção em outro lugar, enquanto seu IDE diz que está tudo perfeitamente bem, então verifique se você está usando as mesmas versões de Java em ambos os lugares.
Por exemplo, Java 7 e Java 8 têm APIs diferentes, portanto, chamar uma API inexistente em uma versão anterior do Java causaria esse erro.
RESOLVIDO
Usando IntelliJ
Selecione Build -> Rebuild Project irá resolvê-lo
Eu também estava recebendo esse erro. (para o qual eu pesquisei 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. Estava recebendo o seguinte erro:
error: cannot find symbol
Solução: Resolvi isso construindo primeiro o projeto onde o método é definido e depois o projeto de onde o método foi chamado.
Se o caminho de construção do eclipse Java for mapeado para 7, 8 e nas propriedades do Maven do projeto pom.xml java.version for mencionada uma versão de Java superior (9,10,11, etc.,) do que 7,8, você precisa atualizar no pom. arquivo xml.
No Eclipse, se o Java é mapeado para Java versão 11 e em pom.xml é mapeado para Java versão 8. Atualize o suporte do Eclipse para Java 11 seguindo as etapas abaixo na Ajuda do Eclipse IDE -> Instalar Novo Software ->
Cole o seguinte link http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With
ou
Adicionar (janela pop-up será aberta) ->
Name:
Suporte a Java 11
Location:
http://download.eclipse.org/eclipse/updates/4.9-P-builds
em seguida, atualize a versão Java nas propriedades 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 no projeto Debug as -> Maven clean, etapas de construção do Maven
Pode haver vários cenários, como as pessoas mencionaram acima. Algumas coisas que me ajudaram a resolver isso.
Se você estiver usando IntelliJ
File -> 'Invalidate Caches/Restart'
OU
A classe que está sendo referenciada estava em outro projeto e essa dependência não foi adicionada ao arquivo de compilação do Gradle do meu projeto. Então, adicionei a dependência usando
compile project(':anotherProject')
e funcionou. HTH!
você compilou seu código usando compilar maven e então usou o teste maven para executá-lo funcionou bem. Agora, se você alterou algo em seu código e, em seguida, sem compilá-lo está executando, você obterá este erro.
Solução: Compile novamente e execute o teste. Para mim, funcionou assim.
No meu caso - tive que realizar as operações abaixo:
- Mova o
context.xml
arquivosrc/java/package
para oresource
diretório (IntelliJ IDE) - Limpe o
target
diretório.
Para dicas, olhe mais de perto o nome da classe que gera um erro e o número da linha, exemplo: Falha de compilação [ERROR] \ applications \ xxxxx.java: [44,30] erro: não é possível encontrar o símbolo
Uma outra causa é o método não suportado para a versão java, digamos jdk7 vs 8. Verifique seu% JAVA_HOME%
Recebemos o erro em um projeto Java configurado como uma compilação de vários projetos do Gradle. Descobriu-se que um dos subprojetos não tinha o plug-in Gradle Java Library . Isso evitou que os arquivos de classe do subprojeto fossem visíveis para outros projetos na construção.
Depois de adicionar o plug-in da biblioteca Java ao subprojeto build.gradle
da seguinte maneira, o erro foi embora:
plugins {
...
id 'java-library'
}
Resolvi esse erro assim ... A loucura do android. Eu tinha o nome do pacote como Adaptador e refatorei o nome para adaptador com um "a" em vez de "A" e resolvi o erro.