2016-04-18 5 views
2

В моем Java приложении, есть метод и имеют следующий код:Локальная переменная Java, доступная изнутри внутреннего класса; должен быть объявлен окончательным, почему он работает в NetBeans?

JButton Button = new JButton(Content); 
Button.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     doSomething(Button.getText()); 
    } 
}); 

Он собирает и работает отлично с NetBeans 8.1, но сегодня, когда я пытался скомпилировать проект из командной строки, он дал мне следующее сообщение об ошибке:

local variable Button is accessed from within inner class; needs to be declared final

Мой вопрос: почему же код соответствует и отлично работает с NetBeans 8.1, но не может скомпилировать в командной строке?

Моя командная строка Java версия: 1.8.0_77

И мой NetBeans Java версия: 1.8.0_65

Это не имеет значения, так почему NetBeans не считает ошибку?

Edit: Woo, BIG СЮРПРИЗ для меня, я просто сделал чек на JAVAC:

C: \ Users \ USER> Java -version Java версии "1.8.0_77"

C: \ Пользователи \ USER> javac -version javac 1.7.0_40

Подождите минуту, я на 100% смущен большим временем, сначала я никогда не знал, что есть команда «javac -version», я думал, что «java -verison» скажу мне как java, так и javac, и я предполагаю, что они одинаковы, во-вторых, когда я установил Java, я думал, что установщик автоматически обновит его, а javac - часть java, поэтому она должна быть внутренне непротиворечивой, но это определенно НЕ, поэтому как моя java -версия отличается от моей javac -version? Другими словами, как я могу доверять Oracle для установки java и javac в одно и то же время, если это не делает работу, значит ли это, что каждый раз, когда я обновляю Java, мне нужно как-то установить мой javac вручную? Я никогда этого не делал, так почему и как это могло произойти?

+1

Какова целевая платформа для вашего проекта Netbeans? Вы уверены, что используете 'javac', который, как вы думаете, используете? Пути командной строки иногда могут вас удивить.Ваш код определенно выглядит так, как будто он должен компилироваться для Java 8. – biziclop

+1

Является ли ваша командная строка предыдущей версией Java, до 1.8? – rgettman

+1

Он должен скомпилировать, проверить версию 'Javac' на командной строке. – 11thdimension

ответ

3

До появления Java 8 все локальные переменные, которые должны быть доступны во внутреннем классе, должны быть объявлены final. Это связано с детальностью реализации - локальные переменные реализуются как скрытые переменные экземпляра внутреннего класса. Если переменную можно изменить, то копия во внутреннем классе будет неправильной.

В Java 8 это требование было ослаблено до «окончательного» или "effectively final" (прокрутите вниз примерно на 2/3 пути).

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.

переменная не должна быть объявлена ​​явно быть final, он просто должен быть эффективно окончательным - явно не final, просто не изменилось.

Вы не меняете Button, так что он действительно окончательный, и он компилируется под Java 8. Однако Java 7 все еще требовал, чтобы он был явно объявлен final, поэтому есть ошибка компилятора.

Исправьте свой путь так, чтобы javac был вашей установкой Java 8. Возможно, у вас есть JRE (нет исполняемого файла javac), который является Java 8, но установка JDK 1.7 (Java 7), которая может объяснить ваш вывод версии. В этом случае вам потребуется загрузить и установить Java 8 JDK (1.8).

Смежные вопросы

 Смежные вопросы