Такое поведение скорее всего связано с переменной %CLASSPATH%
в которой перечислены папки где javac будет искать .class
файлы для компиляции. По умолчанию эта переменная окружения не задана и тогда javac ищет .class
файлы только в текущей папке.
Скорее всего у вас эта переменная была задана ранее (можно проверить при помощи echo %CLASSPATH%
) и тогда текущую папку нужно указывать вручную, например через
javac main.java --class-path .
(.
означает текущую директорию)
Если не хочется каждый раз вручную указывать --class-path .
можно очистить %CLASSPATH%
при помощи set CLASSPATH=
Обратите внимание что необязательно даже вызывать javac Person.java
, компилятор автоматически скомпилирует Person.java
Вот пример запуска на моем компьютере (у меня линукс поэтому синтаксис немного отличается)
~/Workspace$ export CLASSPATH=
~/Workspace$ echo $CLASSPATH
~/Workspace$ javac Person.java
~/Workspace$ javac main.java
~/Workspace$ java main
189
~/Workspace$ export CLASSPATH=/somedirectory
~/Workspace$ echo $CLASSPATH
/somedirectory
~/Workspace$ javac Person.java
~/Workspace$ javac main.java
main.java:3: error: cannot find symbol
Person dima = new Person();
^
symbol: class Person
location: class main
main.java:3: error: cannot find symbol
Person dima = new Person();
^
symbol: class Person
location: class main
2 errors
~/Workspace$ javac main.java --class-path .
~/Workspace$ java main
189
Автор оригинала: baeldung.
1. Обзор
В этом учебнике мы рассмотрим, что такое ошибки компиляции, а затем конкретно объясним, что такое ошибка «не может найти символ» и как она вызвана.
2. Ошибки времени компиляции
Во время компиляции компилятор анализирует и проверяет код на многие вещи; типы ссылок, слепки типов и объявления методов, чтобы назвать несколько. Эта часть процесса компиляции важна, так как на этом этапе мы получим ошибку компиляции.
В основном существует три типа ошибок времени компиляции:
- У нас могут быть синтаксисные . Одна из наиболее распространенных ошибок, которые может сделать любой программист, это забыть поставить заоколонку в конце заявления; некоторые другие забывают импорт, несоответствие скобки, или опуская заявление о возвращении
- Далее, есть ошибки проверки типов. Это процесс проверки безопасности типов в нашем коде. С помощью этой проверки мы убеждаемся, что у нас есть последовательные типы выражений. Например, если мы определяем переменную типа int , мы никогда не должны назначать двойной или Струнные значение для него
- Между тем, существует вероятность того, что компилятор . Это очень редко, но это может произойти. В этом случае хорошо знать, что наш код не может быть проблемой, но что это скорее внешняя проблема
3. Ошибка “не может найти символ”
Ошибка “не может найти символ” возникает в основном, когда мы пытаемся использовать переменную, которая не определена или объявлена в нашей программе.
Когда наш код компилирует, компилятор должен проверить все идентификаторы, которые у нас есть. Ошибка “не может найти символ” означает, что мы ссылаясь на то, что компилятор не знает о .
3.1. Что может вызвать ошибку «не может найти символ»?
Действительно, есть только одна причина: Компилятор не смог найти определение переменной, на которую мы пытаемся ссылаться.
Но, Есть много причин, почему это происходит. Чтобы помочь нам понять, почему, давайте напомним себе, из чего состоит Java-код.
Наш исходный код Java состоит из:
- Ключевые слова: правда, ложь, класс, в то время как
- Буквально: цифры и текст
- Операторы и другие не-альфа-токены: -,/,
- Идентификаторы: основные , Читатель , Я , toString и так далее.
- Комментарии и белое пространство
4. Опечатка
Наиболее распространенные вопросы связаны с орфографией. Если мы вспомним, что все идентификаторы Java чувствительны к случаям, мы можем видеть, что:
- Струнныйбиулдер
- строкаСтроитель
- String_Builder
все это будет по-разному способы неправильно ссылаться на Стрингбилдер класс.
5. Сфера применения экземпляра
Эта ошибка также может быть вызвана при использовании чего-то, что было объявлено вне сферы действия класса.
Допустим, у нас есть Статья класс, который вызывает generateId метод:
public class Article { private int length; private long id; public Article(int length) { this.length = length; this.id = generateId(); } }
Но, мы объявляем generateId метод в отдельном классе:
public class IdGenerator { public long generateId() { Random random = new Random(); return random.nextInt(); } }
С помощью этой настройки компилятор даст ошибку “не может найти символ” для generateId на линии 7 Статья обрезок. Причина в том, что синтаксис строки 7 подразумевает, что generateId метод объявляется в Статья .
Как и во всех зрелых языках, существует несколько способов решения этой проблемы. Но, один из способов было бы построить ИдГенератор в Статья класса, а затем вызвать метод:
public class Article { private int length; private long id; public Article(int length) { this.length = length; this.id = new IdGenerator().generateId(); } }
6. Неопределенные переменные
Иногда мы забываем объявить переменную. Как мы видим из фрагмента ниже, мы пытаемся манипулировать переменной мы не объявили, в данном случае, текстовые :
public class Article { private int length; // ... public void setText(String newText) { this.text = newText; // text variable was never defined } }
Мы решаем эту проблему, объявляя переменную текстовые типа Струнные :
public class Article { private int length; private String text; // ... public void setText(String newText) { this.text = newText; } }
7. Переменный охват
Когда переменная декларация выходит из сферы действия в момент, когда мы пытались использовать ее, это вызовет ошибку во время компиляции. Обычно это происходит, когда мы работаем с петлями.
Переменные внутри цикла недоступны за пределами цикла:
public boolean findLetterB(String text) { for (int i=0; i < text.length(); i++) { Character character = text.charAt(i); if (String.valueOf(character).equals("b")) { return true; } return false; } if (character == "a") { // <-- error! ... } }
если заявление должно идти внутри для петли если нам нужно изучить символы больше:
public boolean findLetterB(String text) { for (int i = 0; i < text.length(); i++) { Character character = text.charAt(i); if (String.valueOf(character).equals("b")) { return true; } else if (String.valueOf(character).equals("a")) { ... } return false; } }
8. Недействительное использование методов или полей
Ошибка “не может найти символ” также произойдет, если мы используем поле в качестве метода или наоборот:
public class Article { private int length; private long id; private List texts; public Article(int length) { this.length = length; } // getters and setters }
Теперь, если мы попытаемся сослаться на тексты поле, как если бы это был метод:
Article article = new Article(300); List texts = article.texts();
то мы увидим ошибку.
Это потому, что компилятор ищет метод под названием тексты , которого нет.
Вообще-то, есть getter метод, который мы можем использовать вместо этого:
Article article = new Article(300); List texts = article.getTexts();
Ошибка работы на массиве, а не элемент массива также является проблемой:
for (String text : texts) { String firstLetter = texts.charAt(0); // it should be text.charAt(0) }
И так забывает новые ключевое слово, как в:
String s = String(); // should be 'new String()'
9. Импорт пакетов и классов
Другая проблема заключается в том, чтобы забыть импортировать класс или пакет. Например, с помощью Список объект без импорта java.util.List :
// missing import statement: // import java.util.List public class Article { private int length; private long id; private List texts; <-- error! public Article(int length) { this.length = length; } }
Этот код не будет компилироваться, так как программа не знает, что Список ош
10. Неправильный импорт
Импорт неправильного типа, из-за завершения IDE или автоматической коррекции также является общей проблемой.
Подумайте о ситуации, когда мы хотим использовать даты в Java. Много раз мы могли бы импортировать неправильный Дата класс, который не предоставляет методы и функции, как другие классы даты, которые нам могут понадобиться:
Date date = new Date(); int year, month, day;
Чтобы получить год, месяц или день для java.util.Date , мы также должны импортировать Календарь класса и извлечь информацию оттуда.
Просто ссылаясь на getDate () из java.util.Date не будет работать:
... date.getDay(); date.getMonth(); date.getYear();
Вместо этого мы используем Календарь объект:
... Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris")); cal.setTime(date); year = cal.get(Calendar.YEAR); month = cal.get(Calendar.MONTH); day = cal.get(Calendar.DAY_OF_MONTH);
Однако, если мы импортировали Местное класса, нам не нужен дополнительный код, который предоставляет нам информацию, в которой мы нуждаемся:
... LocalDate localDate=date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); year = localDate.getYear(); month = localDate.getMonthValue(); day = localDate.getDayOfMonth();
11. Заключение
Компиляторы работают над фиксированным набором правил, которые являются специфическими для языка. Если код не придерживается этих правил, компилятор не может выполнить процесс преобразования, что приводит к ошибке компиляции. Когда мы сталкиваемся с ошибкой компиляции “Не может найти символ”, ключ должен определить причину.
Из сообщения об ошибке мы можем найти строку кода, где происходит ошибка, а какой элемент неправильный. Зная наиболее распространенные проблемы, вызывающие эту ошибку, сделает ее решение очень легко и быстро.
0. Is there any difference between these errors?
Not really. «Cannot find symbol», «Cannot resolve symbol» and «Symbol not found» all mean the same thing. (Different Java compilers are written by different people, and different people use different phraseology to say the same thing.)
1. What does a «Cannot find symbol» error mean?
Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.
Your Java source code consists of the following things:
- Keywords: like
class
,while
, and so on. - Literals: like
true
,false
,42
,'X'
and"Hi mum!"
. - Operators and other non-alphanumeric tokens: like
+
,=
,{
, and so on. - Identifiers: like
Reader
,i
,toString
,processEquibalancedElephants
, and so on. - Comments and whitespace.
A «Cannot find symbol» error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.
A «Cannot find symbol» error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn’t understand.
2. What can cause a «Cannot find symbol» error?
As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn’t find the definition. This could be caused by a number of things. The common ones are as follows:
-
For identifiers in general:
- Perhaps you spelled the name incorrectly; i.e.
StringBiulder
instead ofStringBuilder
. Java cannot and will not attempt to compensate for bad spelling or typing errors. - Perhaps you got the case wrong; i.e.
stringBuilder
instead ofStringBuilder
. All Java identifiers are case sensitive. - Perhaps you used underscores inappropriately; i.e.
mystring
andmy_string
are different. (If you stick to the Java style rules, you will be largely protected from this mistake …) - Perhaps you are trying to use something that was declared «somewhere else»; i.e. in a different context to where you have implicitly told the compiler to look. (A different class? A different scope? A different package? A different code-base?)
- Perhaps you spelled the name incorrectly; i.e.
-
For identifiers that should refer to variables:
- Perhaps you forgot to declare the variable.
- Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
-
For identifiers that should be method or field names:
-
Perhaps you are trying to refer to an inherited method or field that wasn’t declared in the parent / ancestor classes or interfaces.
-
Perhaps you are trying to refer to a method or field that does not exist (i.e. has not been declared) in the type you are using; e.g.
"rope".push()
2. -
Perhaps you are trying to use a method as a field, or vice versa; e.g.
"rope".length
orsomeArray.length()
. -
Perhaps you are mistakenly operating on an array rather than array element; e.g.
String strings[] = ... if (strings.charAt(3)) { ... } // maybe that should be 'strings[0].charAt(3)'
-
-
For identifiers that should be class names:
-
Perhaps you forgot to import the class.
-
Perhaps you used «star» imports, but the class isn’t defined in any of the packages that you imported.
-
Perhaps you forgot a
new
as in:String s = String(); // should be 'new String()'
-
Perhaps you are trying to import or otherwise use a class that has been declared in the default package; i.e. the one where classes with no
package
statements go.Hint: learn about packages. You should only use the default package for simple applications that consist of one class … or at a stretch, one Java source file.
-
-
For cases where type or instance doesn’t appear to have the member (e.g. method or field) you were expecting it to have:
- Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
- Perhaps you are shadowing a static or instance variable.
- Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction may have suggested
java.awt.List
rather thanjava.util.List
. - Perhaps you are using (compiling against) the wrong version of an API.
- Perhaps you forgot to cast your object to an appropriate subclass.
- Perhaps you have declared the variable’s type to be a supertype of the one with the member you are looking for.
The problem is often a combination of the above. For example, maybe you «star» imported java.io.*
and then tried to use the Files
class … which is in java.nio
not java.io
. Or maybe you meant to write File
… which is a class in java.io
.
Here is an example of how incorrect variable scoping can lead to a «Cannot find symbol» error:
List<String> strings = ...
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase("fnord")) {
break;
}
}
if (i < strings.size()) {
...
}
This will give a «Cannot find symbol» error for i
in the if
statement. Though we previously declared i
, that declaration is only in scope for the for
statement and its body. The reference to i
in the if
statement cannot see that declaration of i
. It is out of scope.
(An appropriate correction here might be to move the if
statement inside the loop, or to declare i
before the start of the loop.)
Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable «Cannot find symbol» error:
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
This will give you a compilation error in the println
call saying that i
cannot be found. But (I hear you say) I did declare it!
The problem is the sneaky semicolon ( ;
) before the {
. The Java language syntax defines a semicolon in that context to be an empty statement. The empty statement then becomes the body of the for
loop. So that code actually means this:
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!!
{
System.out.println("i is " + i);
}
The { ... }
block is NOT the body of the for
loop, and therefore the previous declaration of i
in the for
statement is out of scope in the block.
Here is another example of «Cannot find symbol» error that is caused by a typo.
int tmp = ...
int res = tmp(a + b);
Despite the previous declaration, the tmp
in the tmp(...)
expression is erroneous. The compiler will look for a method called tmp
, and won’t find one. The previously declared tmp
is in the namespace for variables, not the namespace for methods.
In the example I came across, the programmer had actually left out an operator. What he meant to write was this:
int res = tmp * (a + b);
There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo
and Bar
where Foo
uses Bar
. If you have never compiled Bar
and you run javac Foo.java
, you are liable to find that the compiler can’t find the symbol Bar
. The simple answer is to compile Foo
and Bar
together; e.g. javac Foo.java Bar.java
or javac *.java
. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.
There are some other more obscure causes too … which I will deal with below.
3. How do I fix these errors ?
Generally speaking, you start out by figuring out what caused the compilation error.
- Look at the line in the file indicated by the compilation error message.
- Identify which symbol that the error message is talking about.
- Figure out why the compiler is saying that it cannot find the symbol; see above!
Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.
Note that not every «correction» is correct. Consider this:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
Suppose that the compiler says «Cannot find symbol» for j
. There are many ways I could «fix» that:
- I could change the inner
for
tofor (int j = 1; j < 10; j++)
— probably correct. - I could add a declaration for
j
before the innerfor
loop, or the outerfor
loop — possibly correct. - I could change
j
toi
in the innerfor
loop — probably wrong! - and so on.
The point is that you need to understand what your code is trying to do in order to find the right fix.
4. Obscure causes
Here are a couple of cases where the «Cannot find symbol» is seemingly inexplicable … until you look closer.
-
Incorrect dependencies: If you are using an IDE or a build tool that manages the build path and project dependencies, you may have made a mistake with the dependencies; e.g. left out a dependency, or selected the wrong version. If you are using a build tool (Ant, Maven, Gradle, etc), check the project’s build file. If you are using an IDE, check the project’s build path configuration.
-
Cannot find symbol ‘var’: You are probably trying to compile source code that uses local variable type inference (i.e. a
var
declaration) with an older compiler or older--source
level. Thevar
was introduced in Java 10. Check your JDK version and your build files, and (if this occurs in an IDE), the IDE settings. -
You are not compiling / recompiling: It sometimes happens that new Java programmers don’t understand how the Java tool chain works, or haven’t implemented a repeatable «build process»; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like.
Another example of this is when you use (Java 9+)
java SomeClass.java
to compile and run a class. If the class depends on another class that you haven’t compiled (or recompiled), you are liable to get «Cannot resolve symbol» errors referring to the 2nd class. The other source file(s) are not automatically compiled. Thejava
command’s new «compile and run» mode is not designed for running programs with multiple source code files. -
An earlier build problem: It is possible that an earlier build failed in a way that gave a JAR file with missing classes. Such a failure would typically be noticed if you were using a build tool. However if you are getting JAR files from someone else, you are dependent on them building properly, and noticing errors. If you suspect this, use
tar -tvf
to list the contents of the suspect JAR file. -
IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists … or the reverse situation.
-
This could happen if the IDE has been configured with the wrong JDK version.
-
This could happen if the IDE’s caches get out of sync with the file system. There are IDE specific ways to fix that.
-
This could be an IDE bug. For instance @Joel Costigliola described a scenario where Eclipse did not handle a Maven «test» tree correctly: see this answer. (Apparently that particular bug was been fixed a long time ago.)
-
-
Android issues: When you are programming for Android, and you have «Cannot find symbol» errors related to
R
, be aware that theR
symbols are defined by thecontext.xml
file. Check that yourcontext.xml
file is correct and in the correct place, and that the correspondingR
class file has been generated / compiled. Note that the Java symbols are case sensitive, so the corresponding XML ids are be case sensitive too.Other symbol errors on Android are likely to be due to previously mention reasons; e.g. missing or incorrect dependencies, incorrect package names, method or fields that don’t exist in a particular API version, spelling / typing errors, and so on.
-
Hiding system classes: I’ve seen cases where the compiler complains that
substring
is an unknown symbol in something like the followingString s = ... String s1 = s.substring(1);
It turned out that the programmer had created their own version of
String
and that his version of the class didn’t define asubstring
methods. I’ve seen people do this withSystem
,Scanner
and other classes.Lesson: Don’t define your own classes with the same names as common library classes!
The problem can also be solved by using the fully qualified names. For example, in the example above, the programmer could have written:
java.lang.String s = ... java.lang.String s1 = s.substring(1);
-
Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.
You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java
uxxxx
escapes for other characters.
1 — If, perchance, you do see this in a runtime exception or error message, then either you have configured your IDE to run code with compilation errors, or your application is generating and compiling code .. at runtime.
2 — The three basic principles of Civil Engineering: water doesn’t flow uphill, a plank is stronger on its side, and you can’t push on a rope.
The Cannot Find Symbol Error in Java error occurs when the Java compiler cannot find a symbol that you are trying to reference in your code. In this article, we will explore how to resolve the “Cannot Find Symbol” error in Java.
The “Cannot Find Symbol” error occurs when you are trying to reference a symbol that has not been defined or imported properly. Symbols can include variables, methods, and classes or in easy language when you try to reference an undeclared variable in your code. The error typically occurs when you have made a typo, used the wrong case in the symbol name, or when you are trying to reference a symbol that is out of scope. You may also encounter this error when you are using multiple files, and the compiler cannot find a class or package that you are trying to reference.
Common mistakes that lead to “Cannot Find Symbol” error in Java and resolving them, you can follow these steps:
- Typos
- Undeclared Variable
- Scope of Current block
- Import Statement
Typos
Make sure that the symbol you are trying to reference is spelled correctly and matches the case used in the definition.
Example 1:
Java
public
class
Main {
static
int
Large(
int
a,
int
b)
{
if
(a > b) {
return
a;
}
else
if
(b > a) {
return
b;
}
else
{
return
-
1
;
}
}
public
static
void
main(String... args)
{
int
value = large(
20
,
4
);
System.out.println(value);
}
}
Output:
./Main.java:17: error: cannot find symbol int value = large(20, 4); ^ symbol: method large(int,int) location: class Main
Explanation of the above program
We get this error as the function we initialized is Large(int a,int b) whereas we are calling large(a,b) so to resolve this typo mistake we just change large to Large.
Example 2:
Java
public
class
Main {
static
int
Large(
int
a,
int
b)
{
if
(a > b) {
return
a;
}
else
if
(b > a) {
return
b;
}
else
{
return
-
1
;
}
}
public
static
void
main(String... args)
{
int
value = Large(
20
,
4
);
System.out.println(value);
}
}
Undeclared Variable
We can also get errors by undeclared Variables.
Example 1:
Java
public
class
Main {
public
static
void
main(String[] args)
{
int
n1 =
500
;
int
n2 =
400
;
sum = n1 + n2;
System.out.println(sum);
}
}
Output:
./Main.java:6: error: cannot find symbol sum = n1 + n2; ^ symbol: variable sum location: class Main ./Main.java:7: error: cannot find symbol System.out.println(sum); ^ symbol: variable sum location: class Main
Explanation of the program
In the above example, the “Cannot find symbol” error occurs as we have not declared the sum. The corrected code is given below (will occur because “sum” is not declared. In order to solve the error, we need to define “int sum = n1+n2” before using the variable sum.
Example 2:
Java
public
class
Main {
public
static
void
main(String[] args)
{
int
n1 =
500
;
int
n2 =
400
;
int
sum = n1 + n2;
System.out.println(sum);
}
}
Check the scope
Make sure that the symbol you are trying to reference is within the scope of the current code block.
Example 1:
Java
public
class
Main {
public
static
void
main(String[] args)
{
int
x =
5
;
if
(x >
0
) {
int
y =
10
;
}
System.out.println(y);
}
}
Output:
./Main.java:8: error: cannot find symbol System.out.println(y); ^ symbol: variable y location: class Main
Explanation of the above program
In this program, we define an integer variable x and initialize it to 5. We then have an if statement that checks if x is greater than 0. If it is, we define another integer variable y, and initialize it to 10. However, y is only within the scope of the if block, and cannot be accessed outside of it.
Example 2:
Java
public
class
Main {
public
static
void
main(String[] args) {
int
x =
5
;
int
y =
0
;
if
(x >
0
) {
y =
10
;
}
System.out.println(y);
}
}
Check the import statements
Make sure that any classes or packages that you are trying to reference are imported properly.
Example 1:
Java
import
java.util.Rand;
public
class
Main {
public
static
void
main(String[] args)
{
Rand rand =
new
Rand();
int
x = rand.nextInt(
10
);
System.out.println(
"Random number: "
+ x);
}
}
Output:
./Main.java:1: error: cannot find symbol import java.util.Rand; ^ symbol: class Rand location: package java.util ./Main.java:6: error: cannot find symbol Rand rand = new Rand(); ^ symbol: class Rand location: class Main ./Main.java:6: error: cannot find symbol Rand rand = new Rand(); ^ symbol: class Rand location: class Main
Example 2:
Java
import
java.util.Random;
public
class
Main {
public
static
void
main(String[] args) {
Random rand =
new
Random();
int
x = rand.nextInt(
10
);
System.out.println(
"Random number: "
+ x);
}
}
Last Updated :
14 May, 2023
Like Article
Save Article
Introduction to Symbol Tables
Symbol tables are an important data structure created and maintained by compilers to store information associated with identifiers [1] in a given source code. This information is entered into the symbol tables during lexical and syntax analysis and is used in the later phases of compilation. As the declarations of classes, interfaces, variables, and methods are processed, their identifiers are bound to corresponding entries in the symbol tables. When uses of these identifiers are encountered in the source code, the compiler looks them up in the symbol tables and relies on this information for things such as verifying that a variable has been declared, determining the scope of a variable, and verifying that an expression is semantically correct with type checking. Symbol tables are also used for code generation and optimization [2].
A simplified representation of a symbol table entry (or simply, a symbol) in Java has the following format: <symbol name (identifier), type, scope, [attributes]>
. Given a global variable declaration like final double ratio;
the corresponding symbol would then be <ratio, double, global, [final]>
.
Install the Java SDK to identify and fix exceptions
Cannot Find Symbol Error
As its name implies, the cannot find symbol
error refers to a symbol which cannot be found. While there are multiple ways and reasons this can occur, they all boil down to the fact that the Java compiler is unable to find the symbol associated with a given identifier.
The message produced by the compiler for the cannot find symbol
error includes two additional fields:
- “symbol”—the name and type of the referenced identifier; and
- “location”—the specific class in which the identifier has been referenced.
What Causes the Cannot Find Symbol Error
The most common triggers for the cannot find symbol
compile-time error include:
- missing variable and method declarations;
- out-of-scope references to variables and methods;
- misspelled identifiers; and
- omitted import statements.
Cannot Find Symbol vs Symbol Not Found vs Cannot Resolve Symbol
As different Java compilers use slightly different terminology, the cannot find symbol
error can also be found under the terms symbol not found
and cannot resolve symbol
. Besides the naming, there is no difference between what these terms stand for.
Cannot Find Symbol Error Examples
Undeclared variable
When the Java compiler encounters a use of an identifier which it cannot find in the symbol table, it raises the cannot find symbol
error. Consequently, the most common occurrence of this error is when there is a reference to an undeclared variable. Unlike some other languages that don’t require explicit declaration of variables [3], or may allow declaring a variable after it has been referenced (via hoisting [4]), Java requires declaring a variable before it can be used or referenced in any way.
Fig. 1(a) shows how an undeclared variable, in this case the identifier average
on line 9, results in two instances of the cannot find symbol
error, at the positions where they appear in the code. Declaring this variable by specifying its data type (or, alternatively, inferring its type with the var
keyword in Java 10+) resolves the issue (Fig. 1(b)).
(a)
1
2
3
4
5
6
7
8
9
10
11
12
package rollbar;
public class UndeclaredVariable {
public static void main(String... args) {
int x = 6;
int y = 10;
int z = 32;
average = (x + y + z) / 3.0; // average is not declared
System.out.println(average);
}
}
UndeclaredVariable.java:9: error: cannot find symbol
average = (x + y + z) / 3.0;
^
symbol: variable average
location: class UndeclaredVariable
UndeclaredVariable.java:10: error: cannot find symbol
System.out.println(average);
^
symbol: variable average
location: class UndeclaredVariable
2 errors
(b)
1
2
3
4
5
6
7
8
9
10
11
12
package rollbar;
public class UndeclaredVariable {
public static void main(String... args) {
int x = 6;
int y = 10;
int z = 32;
double average = (x + y + z) / 3.0;
System.out.println(average);
}
}
16.0
Out of scope variable
When a Java program tries to access a variable declared in a different (non-inherited or non-overlapping) scope, the compiler triggers the cannot find symbol
error. This is demonstrated by the attempt to access the variable counter
on lines 17 and 18 in Fig. 2(a), which is accessible only within the for
statement declared on line 11. Moving the counter
variable outside the for
loop fixes the issue, as shown on Fig. 2(b).
(a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package rollbar;
import java.util.Arrays;
import java.util.List;
public class OutOfScopeVariable {
public static void main(String... args) {
final List<String> strings = Arrays.asList("Hello", "World");
final String searchFor = "World";
for (int counter = 0; counter < strings.size(); counter++) {
if (strings.get(counter).equals(searchFor)) {
break;
}
}
if (counter < strings.size()) {
System.out.println("The word " + searchFor + " was found at index " + counter);
} else {
System.out.println("The word " + searchFor + " wasn't found");
}
}
}
OutOfScopeVariable.java:17: error: cannot find symbol
if (counter < strings.size()) {
^
symbol: variable counter
location: class OutOfScopeVariable
OutOfScopeVariable.java:18: error: cannot find symbol
System.out.println("The word " + searchFor + " was found at index " + counter);
^
symbol: variable counter
location: class OutOfScopeVariable
2 errors
(b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package rollbar;
import java.util.Arrays;
import java.util.List;
public class OutOfScopeVariable {
public static void main(String... args) {
final List<String> strings = Arrays.asList("Hello", "World");
final String searchFor = "World";
int counter;
for (counter = 0; counter < strings.size(); counter++) {
if (strings.get(counter).equals(searchFor)) {
break;
}
}
if (counter < strings.size()) {
System.out.println("The word " + searchFor + " was found at index " + counter);
} else {
System.out.println("The word " + searchFor + " wasn't found");
}
}
}
The word ‘World’ was found at index 1
Misspelled method name
Misspelling an existing method, or any valid identifier, causes a cannot find symbol
error. Java identifiers are case-sensitive, so any variation of an existing variable, method, class, interface, or package name will result in this error, as demonstrated in Fig. 3.
(a)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package rollbar;
public class MisspelledMethodName {
static int fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String... args) {
int fib20 = Fibonacci(20); // Fibonacci ≠ fibonacci
System.out.println(fib20);
}
}
MisspelledMethodName.java:11: error: cannot find symbol
int fib20 = Fibonacci(20);
^
symbol: method Fibonacci(int)
location: class MisspelledMethodName
(b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package rollbar;
public class MisspelledMethodName {
static int fibonacci(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacci(n - 1) + fibonacci(n - 2);
}
public static void main(String... args) {
int fib20 = fibonacci(20);
System.out.println(fib20);
}
}
6765
Missing import statement
Using classes, either from the Java platform or any library, requires importing them correctly with the import
statement. Failing to do so will result in the cannot find symbol
error being raised by the Java compiler. The code snippet in Fig. 4(a) makes use of the java.util.List
class without declaring the corresponding import, therefore the cannot find symbol
error occurs. Adding the missing import
statement (line 4 in Fig. 4(b)) solves the problem.
(a)
package rollbar;
import java.util.Arrays;
public class MissingImportList {
private static final List<String> CONSTANTS = Arrays.asList("A", "B", "C");
public static void main(String... args) {
System.out.println(CONSTANTS);
}
}
MissingImportList.java:6: error: cannot find symbol
private static final List<String> CONSTANTS = Arrays.asList("A", "B", "C");
^
symbol: class List
location: class MissingImportList
(b)
1
2
3
4
5
6
7
8
9
10
11
12
package rollbar;
import java.util.Arrays;
import java.util.List;
public class MissingImportList {
private static final List<String> CONSTANTS = Arrays.asList("A", "B", "C");
public static void main(String... args) {
System.out.println(CONSTANTS);
}
}
[A, B, C]
Less common examples
The root cause for the cannot find symbol
Java error can occasionally be found in some unexpected or obscure places. Such is the case with accidental semicolons that terminate a statement ahead of time (Fig. 5), or when object creation is attempted without a proper constructor invocation which has to have the new
keyword (Fig. 6).
(a)
package rollbar;
public class LoopScope {
public static void main(String... args) {
int start = 1, end = 10;
for (int i = start; i <= end; i++); {
System.out.print(i == end ? i : i + ", ");
}
}
}
LoopScope.java:7: error: cannot find symbol
System.out.print(i == end ? i : i + ", ");
^
symbol: variable i
location: class LoopScope
LoopScope.java:7: error: cannot find symbol
System.out.print(i == end ? i : i + ", ");
^
symbol: variable i
location: class LoopScope
LoopScope.java:7: error: cannot find symbol
System.out.print(i == end ? i : i + ", ");
^
symbol: variable i
location: class LoopScope
3 errors
(b)
package rollbar;
public class LoopScope {
public static void main(String... args) {
int start = 1, end = 10;
for (int i = start; i <= end; i++) {
System.out.print(i == end ? i : i + ", ");
}
}
}
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
(a)
package rollbar;
public class ObjectCreation {
public static void main(String... args) {
String s = String("Hello World!");
System.out.println(s);
}
}
ObjectCreation.java:5: error: cannot find symbol
String s = String("Hello World!");
^
symbol: method String(String)
location: class ObjectCreation
(b)
package rollbar;
public class ObjectCreation {
public static void main(String... args) {
String s = new String("Hello World!");
System.out.println(s);
}
}
Hello World!
Other causes for the cannot find symbol
error may include:
- using dependencies with old or incompatible versions;
- forgetting to recompile a program;
- building a project with an older JDK version;
- redefining platform or library classes with the same name;
- the use of homoglyphs in identifier construction that are difficult to tell apart;
- etc.
Conclusion
The cannot find symbol
error, also found under the names of symbol not found
and cannot resolve symbol
, is a Java compile-time error which emerges whenever there is an identifier in the source code which the compiler is unable to work out what it refers to. As with any other compilation error, it is crucial to understand what causes this error, pinpoint the issue and address it properly. In the majority of cases, referencing undeclared variables and methods, including by way of misspelling them or failing to import their corresponding package, is what triggers this error. Once discovered, resolution is pretty straightforward, as demonstrated in this article.
Track, Analyze and Manage Errors With Rollbar
Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!
References
[1] Rollbar, 2021. Handling the <Identifier> Expected Error in Java. Rollbar Editorial Team. [Online]. Available: https://rollbar.com/blog/how-to-handle-the-identifier-expected-error-in-java/. [Accessed Nov. 22, 2021].
[2] ITL Education Solutions Limited, Principles of Compiler Design (Express Learning), 1st ed. New Delhi: Pearson Education (India), 2012.
[3] Tutorialspoint.com, 2021. Python — Variable Types. [Online]. Available: https://www.tutorialspoint.com/python/python_variable_types.htm. [Accessed: Nov. 23, 2021].
[4] JavaScript Tutorial, 2021. JavaScript Hoisting Explained By Examples. [Online]. Available: https://www.javascripttutorial.net/javascript-hoisting/. [Accessed: Nov. 23, 2021]