0. Есть ли разница между двумя ошибками?
На самом деле, нет. «Не удается найти символ» и «Не удается найти символ» означают одно и то же. Некоторые компиляторы Java используют одну фразу, а некоторые - другую.
1. Что означает ошибка «Не удается найти символ»?
Во-первых, это ошибка компиляции 1 . Это означает, что либо проблема в исходном коде Java, либо в способе его компиляции.
Ваш исходный код Java состоит из следующих вещей:
- Ключевые слова: как
true
, false
, class
, while
и так далее.
- Литералы: как
42
и 'X'
и "Hi mum!"
.
- Операторы и другие не буквенно-цифровые маркеры: как
+
, =
, {
и так далее.
- Идентификаторы: как
Reader
, i
, toString
, processEquibalancedElephants
и так далее.
- Комментарии и пробелы.
Ошибка «Не удается найти символ» связана с идентификаторами. Когда ваш код скомпилирован, компилятору необходимо выяснить, что означает каждый идентификатор в вашем коде.
Ошибка «Не удается найти символ» означает, что компилятор не может этого сделать. Похоже, ваш код ссылается на то, что компилятор не понимает.
2. Что может вызвать ошибку «Не удается найти символ»?
Как первый заказ, есть только одна причина. Компилятор просмотрел все места, где должен быть определен идентификатор , и не смог найти определение. Это может быть вызвано рядом вещей. Общие из них следующие:
- Для идентификаторов в целом:
- Возможно, вы написали имя неправильно; т.е.
StringBiulder
вместо StringBuilder
. Java не может и не будет пытаться компенсировать плохие орфографические или опечатки.
- Возможно, вы ошиблись; т.е.
stringBuilder
вместо StringBuilder
. Все идентификаторы Java чувствительны к регистру.
- Возможно, вы неправильно использовали подчеркивание; то есть
mystring
и my_string
разные. (Если вы будете придерживаться правил стиля Java, вы будете в значительной степени защищены от этой ошибки ...)
- Возможно, вы пытаетесь использовать то, что было объявлено «где-то еще»; то есть в другом контексте, где вы явно указали компилятору искать. (Другой класс? Другая область применения? Другой пакет? Другая база кода?)
- Для идентификаторов, которые должны ссылаться на переменные:
- Возможно, вы забыли объявить переменную.
- Возможно, объявление переменной выходит за рамки того, что вы пытались использовать. (См. Пример ниже)
Для идентификаторов, которые должны быть именами методов или полей:
- Возможно, вы пытаетесь сослаться на унаследованный метод или поле, которое не было объявлено в классах или интерфейсах родителя / предка.
- Возможно, вы пытаетесь сослаться на метод или поле, которые не существуют (т.е. не были объявлены) в используемом вами типе; например
"someString".push()
2 .
- Возможно, вы пытаетесь использовать метод в качестве поля или наоборот; например
"someString".length
или someArray.length()
.
Возможно, вы ошибочно работаете с массивом, а не с элементом массива; например
String strings[] = ...
if (strings.charAt(3)) { ... }
// maybe that should be 'strings[0].charAt(3)'
Для идентификаторов, которые должны быть именами классов:
- Возможно, вы забыли импортировать класс.
- Возможно, вы использовали импорт «звезда», но класс не определен ни в одном из импортированных вами пакетов.
Возможно, вы забыли, new
как в:
String s = String(); // should be 'new String()'
Для случаев, когда тип или экземпляр не имеют члена, которого вы ожидали иметь:
- Возможно, вы объявили вложенный класс или универсальный параметр, который скрывает тип, который вы хотели использовать.
- Возможно, вы отслеживаете статическую переменную или переменную экземпляра.
- Возможно, вы импортировали неправильный тип; например, из-за завершения IDE или автокоррекции.
- Возможно, вы используете (компилируете) не ту версию API.
- Возможно, вы забыли привести свой объект к соответствующему подклассу.
Проблема часто заключается в сочетании вышеперечисленного. Например, может быть, вы импортировали "звезду", java.io.*
а затем пытались использовать Files
класс ... которого java.nio
нет java.io
. Или , может быть , вы имели в виду , чтобы написать File
... который является классом в java.io
.
Вот пример того, как неправильная область видимости переменной может привести к ошибке «Не удается найти символ»:
List<String> strings = ...
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase("fnord")) {
break;
}
}
if (i < strings.size()) {
...
}
Это даст «Не удается найти символ» ошибка для i
в if
заявлении. Хотя мы ранее заявили i
, что заявление только в области видимости для for
заявления и его тела. Ссылка i
в if
заявлении не может видеть эту декларацию i
. Это выходит за рамки .
(Соответствующее исправление здесь может заключаться в том, чтобы переместить if
инструкцию внутри цикла или объявить i
до начала цикла.)
Вот пример, который вызывает недоумение, когда опечатка приводит к, казалось бы, необъяснимой ошибке «Не удается найти символ»:
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
Это даст вам ошибку компиляции в println
вызове, сказав, что i
не может быть найден. Но (я слышу, вы говорите), я это объявил!
Проблема в хитрой точке с запятой ( ;
) перед {
. Синтаксис языка Java определяет точку с запятой в этом контексте как пустой оператор . Пустой оператор становится телом for
цикла. Так что код на самом деле означает это:
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!!
{
System.out.println("i is " + i);
}
{ ... }
Блок НЕ тело for
цикла, и , следовательно, предыдущая декларация i
в for
утверждение из области видимости в блоке.
Вот еще один пример ошибки «Не удается найти символ», вызванной опечаткой.
int tmp = ...
int res = tmp(a + b);
Несмотря на предыдущей декларации, то tmp
в tmp(...)
выражении является ошибочным. Компилятор будет искать вызываемый метод tmp
и не найдет его. Ранее объявленное tmp
находится в пространстве имен для переменных, а не в пространстве имен для методов.
В приведенном мной примере программист фактически исключил оператор. Он хотел написать следующее:
int res = tmp * (a + b);
Есть еще одна причина, по которой компилятор может не найти символ, если вы компилируете из командной строки. Возможно, вы просто забыли скомпилировать или перекомпилировать какой-то другой класс. Например, если у вас есть классы Foo
и Bar
где Foo
используется Bar
. Если вы никогда не компилировали Bar
и запускали javac Foo.java
, вы наверняка обнаружите, что компилятор не может найти символ Bar
. Простой ответ - собрать Foo
и собрать Bar
вместе; например javac Foo.java Bar.java
или javac *.java
. Или лучше использовать инструмент сборки Java; например муравей, мавен, градль и так далее.
Есть и другие, более неясные причины ... о которых я расскажу ниже.
3. Как я могу исправить эти ошибки?
Вообще говоря, вы начинаете путем выяснить , что вызвало ошибку компиляции.
- Посмотрите на строку в файле, обозначенную сообщением об ошибке компиляции.
- Определите символ, о котором говорится в сообщении об ошибке.
- Выясните, почему компилятор говорит, что он не может найти символ; смотри выше!
Затем вы думаете о том, что ваш код должен говорить. Затем, наконец, вы решаете, какое исправление необходимо внести в исходный код, чтобы сделать то, что вы хотите.
Обратите внимание, что не каждая «коррекция» является правильной. Учти это:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
Предположим, что компилятор говорит «Не удается найти символ» для j
. Есть много способов, которыми я мог бы «исправить» это:
- Я мог бы изменить внутреннее
for
на for (int j = 1; j < 10; j++)
- возможно, правильно.
- Я мог бы добавить объявление для
j
перед внутренним for
циклом, или внешний for
цикл - возможно, правильный.
- Я мог бы изменить ,
j
чтобы i
во внутреннем for
цикле - вероятно , неправильно!
- и так далее.
Дело в том, что вам нужно понять, что ваш код пытается сделать, чтобы найти правильное решение.
4. Неясные причины
Вот пара случаев, когда «Не удается найти символ» кажется необъяснимым ... пока вы не посмотрите ближе.
Неверные зависимости : если вы используете IDE или инструмент сборки, который управляет путем сборки и зависимостями проекта, возможно, вы допустили ошибку с зависимостями; например, исключил зависимость или выбрал неправильную версию. Если вы используете инструмент сборки (Ant, Maven, Gradle и т. Д.), Проверьте файл сборки проекта. Если вы используете IDE, проверьте конфигурацию пути сборки проекта.
Вы не перекомпилируете : иногда случается, что новые Java-программисты не понимают, как работает цепочка инструментов Java, или не реализуют повторяемый «процесс сборки»; например, используя IDE, Ant, Maven, Gradle и так далее. В такой ситуации программист может в итоге гоняться за хвостом в поисках иллюзорной ошибки, которая на самом деле вызвана неправильной перекомпиляцией кода и тому подобным ...
Проблема с более ранней сборкой . Возможно, что более ранняя сборка завершилась неудачно, что дало JAR-файл с отсутствующими классами. Такой сбой, как правило, будет замечен, если вы используете инструмент сборки. Однако, если вы получаете файлы JAR от кого-то другого, вы зависите от их правильной сборки и замечаете ошибки. Если вы подозреваете это, используйте tar -tvf
для просмотра содержимого подозрительного файла JAR.
Проблемы IDE : Люди сообщали о случаях, когда их IDE запутывается, и компилятор в IDE не может найти класс, который существует ... или обратная ситуация.
Это может произойти, если IDE была настроена с неверной версией JDK.
Это может произойти, если кэши IDE не синхронизируются с файловой системой. Есть конкретные способы, чтобы исправить это.
Это может быть ошибка IDE. Например, @Joel Costigliola описывает сценарий, в котором Eclipse неправильно обрабатывает «тестовое» дерево Maven: см. Этот ответ .
Проблемы с Android : когда вы программируете для Android и у вас есть ошибки «Не удается найти символ» R
, имейте в виду, что R
символы определены context.xml
файлом. Убедитесь, что ваш context.xml
файл правильный и в правильном месте, и что соответствующий R
файл класса был сгенерирован / скомпилирован. Обратите внимание, что символы Java чувствительны к регистру, поэтому соответствующие идентификаторы XML также чувствительны к регистру.
Другие ошибки символов в Android, скорее всего, связаны с ранее упомянутыми причинами; например, отсутствующие или неправильные зависимости, неправильные имена пакетов, методы или поля, которых нет в конкретной версии API, ошибки правописания / набора текста и т. д.
Переопределение системных классов : я видел случаи, когда компилятор жалуется, что substring
это неизвестный символ в чем-то вроде следующего
String s = ...
String s1 = s.substring(1);
Оказалось, что программист создал свою собственную версию String
и что его версия класса не определила substring
методы.
Урок: не определяйте свои собственные классы с такими же именами, как у обычных библиотечных классов!
Гомоглифы: если вы используете кодировку UTF-8 для своих исходных файлов, возможно, что идентификаторы выглядят одинаково, но на самом деле они разные, поскольку содержат гомоглифы. Смотрите эту страницу для получения дополнительной информации.
Вы можете избежать этого, ограничив себя ASCII или Latin-1 в качестве кодировки исходного файла и используя Java- \uxxxx
экранирование для других символов.
1 - Если, возможно, вы бы увидеть это в исключение во время выполнения или сообщение об ошибке, то либо вы настроили IDE для кода выполнения с ошибками компиляции, или приложение генерирует и компиляции кода .. во время выполнения.
2 - Три основных принципа гражданского строительства: вода не течет в гору, доска сильнее на ее стороне, и вы не можете толкнуть веревку .
println
вSystem.out.println
случае размещения на уровне класса в стандартном компиляторе мы получим<identifier> expected
( demo ), но в IntelliJ мы увидимCannot resolve symbol 'println'
( demo ).Вы также получите эту ошибку, если забудете
new
:против
потому что вызов без
new
ключевого слова попытается найти (локальный) метод, вызываемыйString
без аргументов - и эта сигнатура метода, вероятно, не определена.источник
Еще один пример «Переменная выходит за рамки»
Как я уже видел подобные вопросы несколько раз, может быть, это еще один пример того, что незаконно, даже если это может показаться нормальным.
Рассмотрим этот код:
Это неверный код. Потому что ни одна из названных переменных
message
не видна за пределами их соответствующей области видимости - которые{}
в этом случае будут окружающими скобками .Вы можете сказать: «Но переменная с именем сообщения определяется в любом случае - так сообщение будет определено после
if
».Но ты ошибаешься.
Java не имеет операторов
free()
илиdelete
, поэтому она должна полагаться на отслеживание области видимости переменных, чтобы выяснить, когда переменные больше не используются (вместе со ссылками на эти переменные причины).Особенно плохо, если ты думал, что сделал что-то хорошее. Я видел такую ошибку после «оптимизации» кода, например:
«О, есть дублированный код, давайте вытянем эту общую строку» -> и вот оно.
Наиболее распространенный способ решения этой проблемы - это предварительно назначить значения else для имен переменных во внешней области, а затем переназначить, если:
источник
final
объявление переменной.Один из способов получить эту ошибку в Eclipse:
A
вsrc/test/java
.B
вsrc/main/java
который использует классA
.Результат: Eclipse скомпилирует код, но maven выдаст «Cannot find symbol».
Основная причина: Eclipse использует комбинированный путь сборки для основного и тестового деревьев. К сожалению, он не поддерживает использование разных путей сборки для разных частей проекта Eclipse, чего требует Maven.
Решение :
источник
«Не удается найти» означает, что компилятор, который не может найти подходящую переменную, метод, класс и т. Д. Если вы получили этот массаж ошибок, в первую очередь вы хотите найти строку кода, в которой получите массаж ошибок… И тогда вы будете возможность найти, какую переменную, метод или класс не определили до его использования. После подтверждения инициализации эту переменную, метод или класс можно использовать для последующего использования ... Рассмотрим следующий пример.
Я создам демонстрационный класс и напечатаю имя ...
Теперь посмотрим на результат ..
Эта ошибка говорит, что «имя переменной не может быть найдено». Определение и инициализация значения для переменной «имя» можно отменить эту ошибку .. На самом деле, как это,
Теперь посмотрим на новый вывод ...
Хорошо, успешно удалось решить эту ошибку. В то же время, если вы можете получить что-то «не могу найти метод» или «не можете найти класс», сначала определите класс или метод, а затем используйте это ..
источник
Если вы получаете эту ошибку в сборке где-то еще, в то время как ваша IDE говорит, что все отлично, то убедитесь, что вы используете одинаковые версии Java в обоих местах.
Например, Java 7 и Java 8 имеют разные API, поэтому вызов несуществующего API в более старой версии Java может вызвать эту ошибку.
источник
Я тоже получал эту ошибку. (за что я погуглил и меня направили на эту страницу)
Проблема: я вызывал статический метод, определенный в классе проекта A, из класса, определенного в другом проекте B. Я получил следующую ошибку:
Решение: я решил эту проблему, сначала создав проект, в котором определяется метод, а затем проект, из которого вызывался метод.
источник
Если eclipse Java build path сопоставлен с 7, 8 и в свойствах Project pom.xml Maven java.version упоминается более высокая версия Java (9,10,11 и т. Д.,), Чем 7,8, вам необходимо обновить ее в pom. XML-файл.
В Eclipse, если Java сопоставлена с Java версии 11, а в pom.xml она сопоставлена с Java версии 8. Обновите поддержку Eclipse до Java 11, выполнив следующие шаги в справке IDE eclipse -> Установить новое программное обеспечение ->
Вставьте следующую ссылку http://download.eclipse.org/eclipse/updates/4.9-P-builds при работе с
или
Добавить (откроется всплывающее окно) ->
Name:
Поддержка Java 11Location:
http://download.eclipse.org/eclipse/updates/4.9-P-buildsзатем обновите версию Java в свойствах Maven файла pom.xml, как показано ниже
Наконец, щелкните правой кнопкой мыши на проекте Debug as -> Maven clean, шаги сборки Maven.
источник
РЕШИТЬ
Выберите Build -> Rebuild Project, чтобы решить его
источник
Как уже упоминалось выше, могут быть разные сценарии. Несколько вещей, которые помогли мне решить эту проблему.
Если вы используете IntelliJ
File -> 'Invalidate Caches/Restart'
ИЛИ
Указанный класс находился в другом проекте, и эта зависимость не была добавлена в файл сборки Gradle моего проекта. Поэтому я добавил зависимость, используя
compile project(':anotherProject')
и это сработало. НТН!
источник
Вы скомпилировали свой код с помощью maven compile, а затем использовали maven test, чтобы он работал нормально. Теперь, если вы изменили что-то в своем коде, а затем без компиляции запускаете его, вы получите эту ошибку.
Решение: Снова скомпилируйте и запустите тест. Для меня это сработало так.
источник
В моем случае - мне пришлось выполнить следующие операции:
context.xml
файл изsrc/java/package
вresource
каталог (IntelliJ IDE)target
каталог.источник
Для подсказок, посмотрите ближе на имя класса, которое выдает ошибку и номер строки, например: Ошибка компиляции [ОШИБКА] \ Applications \ xxxxx.java: [44,30] Ошибка: не удается найти символ
Еще одна причина - неподдерживаемый метод для java версии, скажем, jdk7 против 8. Проверьте ваш% JAVA_HOME%
источник