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
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 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
StringBiulder
vez 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
stringBuilder
vez de StringBuilder
. Todos os identificadores Java diferenciam maiúsculas de minúsculas.
- Talvez você tenha usado sublinhados inadequadamente; ou seja,
mystring
e my_string
sã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".length
ou 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:
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 Files
classe ... que java.nio
nã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" i
na if
instrução. Embora tenhamos declarado anteriormente i
, essa declaração está apenas no escopo da for
declaração e de 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 para dentro do loop ou declarar i
antes 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 println
chamada dizendo que i
nã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 for
loop. 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 for
loop, e, portanto, a declaração anterior de i
na for
declaraçã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, tmp
a tmp(...)
expressão está incorreta. O compilador procurará um método chamado tmp
e não o encontrará. O declarado anteriormente tmp
está 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 Foo
e Bar
onde Foo
usa Bar
. Se você nunca compilou Bar
e executou javac Foo.java
, é provável que descubra que o compilador não pode encontrar o símbolo Bar
. A resposta simples é compilar Foo
e Bar
juntos; 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 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
for
para for (int j = 1; j < 10; j++)
- provavelmente correto.
- Eu poderia adicionar uma declaração
j
antes do for
loop interno ou externo for
- possivelmente correto.
- Eu poderia mudar
j
para i
no for
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 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.
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.
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 ...
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 -tvf
para listar o conteúdo do arquivo JAR suspeito.
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 .
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 R
símbolos são definidos pelo context.xml
arquivo. Verifique se o seu context.xml
arquivo está correto e no lugar correto, e se o R
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.
É 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.
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 String
e que sua versão da classe não definia um substring
método.
Lição: não defina suas próprias classes com os mesmos nomes que as classes comuns da biblioteca!
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 \uxxxx
escapes 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 .