Вы установили плагин Advanced Java Folding , который делает именно то, что вы видите, сбрасывает и аббревиатура некоторых языковых конструкций.
Либо удалить / отключить подключаемый модуль или настроить его варианты в соответствии с вашими личными предпочтениями:
Хотя эти ответы интеллектуально интересны, я не прочел короткий простой ответ:
Используйте ключевое слово final , когда вы хотите, чтобы компилятор запретил перегруппировку переменной для другого объекта.
blockquote>Является ли переменная статической переменной, переменной-членом, локальной переменной или аргументом / параметром
Пример
Давайте посмотрим на эффект в действии.
Рассмотрим этот простой метод, где две переменные ( arg и x ) оба могут быть повторно назначены разные объекты.
// Example use of this method: // this.doSomething( "tiger" ); void doSomething( String arg ) { String x = arg; // Both variables now point to the same String object. x = "elephant"; // This variable now points to a different String object. arg = "giraffe"; // Ditto. Now neither variable points to the original passed String. }
Отметьте локальную переменную как final . Это приводит к ошибке компилятора.
void doSomething( String arg ) { final String x = arg; // Mark variable as 'final'. x = "elephant"; // Compiler error: The final local variable x cannot be assigned. arg = "giraffe"; }
Вместо этого отметим параметрную переменную как final . Это также приводит к ошибке компилятора.
void doSomething( final String arg ) { // Mark argument as 'final'. String x = arg; x = "elephant"; arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object. }
Мораль истории:
Если вы хотите, чтобы переменная всегда указывала на один и тот же объект, отметьте переменную final .
blockquote>Никогда не переназначайте аргументы
Как хорошая практика программирования (на любом языке), вы должны никогда повторно назначить переменную параметра / аргумента объекту, отличному от объекта, переданного вызывающим методом. В приведенных выше примерах никогда не следует писать строку
arg =
. Поскольку люди делают ошибки, а программисты - люди, давайте попросим компилятор помочь нам. Пометьте каждую переменную параметра / аргумента как «final», чтобы компилятор мог найти и помечать любые такие перераспределения.В Retrospect
Как отмечено в других ответах ... Учитывая оригинальный дизайн Java цель помочь программистам избежать немых ошибок, таких как чтение за концом массива, Java должен был быть разработан для автоматического принудительного применения всех переменных параметра / аргумента как «final». Другими словами, Аргументы не должны быть переменными . Но задним числом является 20/20 видение, и разработчики Java в свое время были в полной мере.
В дополнение к полноте
public class MyClass { private int x; //getters and setters } void doSomething( final MyClass arg ) { // Mark argument as 'final'. arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object. arg.setX(20); // allowed // We can re-assign properties of argument which is marked as final }
Короткий ответ: final
помогает маленькому биту, но ... вместо этого используйте защитное программирование на стороне клиента.
Действительно, проблема с final
в том, что она только обеспечивает, чтобы ссылка не изменялась , радостно позволяя связанным объектам-объектам быть мутированными, без ведома вызывающего. Следовательно, наилучшей практикой в этом отношении является защитное программирование со стороны вызывающего абонента, создающее глубоко неизменные экземпляры или глубокие копии объектов, которым грозит опасность недобросовестных API.
Я использую окончательное все время по параметрам.
Значит ли это так много? Не совсем.
Могу ли я отключить его? Нет.
Причина: я обнаружил 3 ошибки, когда люди написали неаккуратный код и не смогли установить переменную-член в accessors. Все ошибки оказались труднодоступными.
Хотелось бы, чтобы это сделало дефолт в будущей версии Java. Передача по значению / справочной вещи вызывает множество программистов младшего возраста.
Еще одна вещь. Мои методы имеют низкое количество параметров, поэтому дополнительный текст в объявлении метода не является проблемой.
Использование final в параметре метода не имеет ничего общего с тем, что происходит с аргументом на стороне вызывающего абонента. Это означает, что это не изменяется внутри этого метода. Когда я пытаюсь принять более функциональный стиль программирования, я как бы вижу значение в этом.
final
параметры в описаниях интерфейсов / абстрактных методов.
– Beni Cherniavsky-Paskin
22 March 2015 в 13:53
Иногда приятно быть явным (для удобочитаемости), что переменная не изменяется. Вот простой пример, когда использование final может сэкономить некоторые возможные головные боли
public void setTest(String test) {
test = test;
}
, если вы забыли это ключевое слово на сеттере, переменная, которую вы хотите установить, не будет установлена. Однако, если вы использовали ключевое слово final для параметра, тогда ошибка будет обнаружена во время компиляции.
Да, исключая анонимные классы, читаемость и декларирование намерений, это почти бесполезно. Эти три вещи бесполезны?
Лично я склонен не использовать final
для локальных переменных и параметров, если я не использую эту переменную в анонимном внутреннем классе, но я, безусловно, могу видеть смысл этих которые хотят дать понять, что само значение параметра не изменится (даже если объект, на который он ссылается, изменит его содержимое).
Ваш вопрос был бы более важным, если бы кто-то действительно утверждал, что он сделал , чтобы данные были постоянными таким образом, что это не так, - но я не могу вспомнить, что видел такие претензии. Вы предполагаете, что существует значительное количество разработчиков, предлагающих, что final
обладает большим эффектом, чем это действительно делает?
EDIT: Я действительно должен был бы суммировать все это с помощью ссылки Monty Python; вопрос кажется несколько похожим на вопрос: «Что римляне когда-либо делали для нас?»
Я никогда не использую final в списке параметров, он просто добавляет беспорядок, как говорили предыдущие респонденты. Также в Eclipse вы можете установить назначение параметров для генерации ошибки, поэтому использование final в списке параметров кажется мне излишним. Интересно, когда я включил параметр Eclipse для назначения параметров, генерируя ошибку, он поймал этот код (это как раз то, как я помню поток, а не фактический код.): -
private String getString(String A, int i, String B, String C)
{
if (i > 0)
A += B;
if (i > 100)
A += C;
return A;
}
Играя адвоката дьявола, что именно не так с этим?
Следуйте за сообщением Мишеля. Я сам сделал себе еще один пример, чтобы объяснить это. Я надеюсь, что это могло бы помочь.
public static void main(String[] args){
MyParam myParam = thisIsWhy(new MyObj());
myParam.setArgNewName();
System.out.println(myParam.showObjName());
}
public static MyParam thisIsWhy(final MyObj obj){
MyParam myParam = new MyParam() {
@Override
public void setArgNewName() {
obj.name = "afterSet";
}
@Override
public String showObjName(){
return obj.name;
}
};
return myParam;
}
public static class MyObj{
String name = "beforeSet";
public MyObj() {
}
}
public abstract static class MyParam{
public abstract void setArgNewName();
public abstract String showObjName();
}
Из приведенного выше кода в методе thisIsWhy () мы фактически не присвоили [аргумент MyObj obj] реальную ссылку в MyParam. Вместо этого мы просто используем [аргумент MyObj obj] в методе внутри MyParam.
Но после завершения метода thisIsWhy (), должен существовать аргумент (объект) MyObj?
Похоже, должно быть, потому что мы можем видеть в основном, мы все еще вызываем метод showObjName (), и ему нужно достичь obj. MyParam все еще использует / достигает аргумента метода, даже если метод уже возвращался!
Как Java действительно достигает этого - сгенерировать копию, также является скрытой ссылкой аргумента MyObj obj внутри объекта MyParam (но это не формальное поле в MyParam, так что мы не можем его увидеть)
Как мы называем «showObjName», он будет использовать эту ссылку для получения соответствующего значения.
Но если мы не представим аргумент final, что приведет к ситуации, мы можем переназначить новая память (объект) к аргументу MyObj obj.
Технически нет никакого столкновения! Если нам будет позволено это сделать, ниже будет ситуация:
Нет столкновения, но «CONFUSING! !» Потому что все они используют одно и то же «ссылочное имя», которое является «obj».
Чтобы избежать этого, установите его как «final», чтобы программатор не выполнял «код, подверженный ошибкам».
Поскольку Java передает копии аргументов, я считаю, что ее значимость весьма ограничена. Я предполагаю, что это происходит из эпохи C ++, где вы можете запретить ссылочный контент для изменения, выполнив const char const *
. Я чувствую, что такие вещи заставляют вас полагать, что разработчику присуще глупо, как f ***, и его нужно защищать от поистине каждого персонажа, которого он набирает. Во всех смирениях я должен сказать, что я пишу очень мало ошибок, хотя я опускаю final
, если только я не хочу, чтобы кто-то переоценивал мои методы и прочее ... Может быть, я просто девчонка старой школы ... : -O
Позвольте мне немного рассказать об одном случае, когда вы использовали для использования final, о котором уже упоминал Джон:
Если вы создаете анонимный внутренний класс в своем методе и используете локальная переменная (такая как параметр метода) внутри этого класса, тогда компилятор заставляет вас сделать параметр final:
public Iterator<Integer> createIntegerIterator(final int from, final int to)
{
return new Iterator<Integer>(){
int index = from;
public Integer next()
{
return index++;
}
public boolean hasNext()
{
return index <= to;
}
// remove method omitted
};
}
Здесь параметры from
и to
должны быть окончательными, поэтому они могут использоваться внутри анонимного класса.
Причина этого требования такова: локальные переменные живут в стеке, поэтому они существуют только при выполнении метода. Однако экземпляр анонимного класса возвращается из метода, поэтому он может жить намного дольше. Вы не можете сохранить стек, потому что это необходимо для последующих вызовов методов.
Таким образом, вместо того, чтобы вместо Java использовать копии этих локальных переменных в качестве скрытых переменных экземпляра в анонимный класс, вы можете увидеть их (если вы посмотрите на байтовый код). Но если они не были окончательными, можно было бы ожидать, что анонимный класс и метод, видя изменения, другой, внесенный в переменную. Чтобы сохранить иллюзию, что есть только одна переменная, а не две копии, она должна быть окончательной.
final
и не конечным параметром функции в глазах HotSpot?
– Pacerier
17 November 2011 в 14:34
Еще одна причина добавления окончательных объявлений в параметры состоит в том, что он помогает идентифицировать переменные, которые необходимо переименовать как часть рефакторинга «Метод извлечения». Я обнаружил, что добавление окончательного значения для каждого параметра перед началом рефакторинга большого метода быстро говорит мне, есть ли какие-либо проблемы, которые мне нужно решить, прежде чем продолжить.
Однако я обычно удаляю их как лишние в конце рефакторинг.
Лично я не использую final в параметрах метода, потому что он добавляет слишком много беспорядка в списки параметров. Я предпочитаю, чтобы эти параметры метода не менялись с помощью чего-то вроде Checkstyle.
Для локальных переменных я использую final по возможности, даже позволяю Eclipse делать это автоматически в моей настройке для личных проектов.
Мне бы, конечно, понравилось нечто вроде C / C ++ const.
message = ( msg || 'Hello World"' )
. Просто нет причины not i> использовать отдельный var. Единственная стоимость - это несколько байтов памяти. – Basil Bourque 27 November 2013 в 23:07message = ( msg || 'Hello World"' )
, я рискую позже, используяmsg
. Когда контракт, который я намереваюсь, имеет «поведение без аргумента / null / undefined arg, является неотличимым от передачи"Hello World"
», хорошая практика программирования заключается в том, чтобы зафиксировать его в начале функции. [Это может быть достигнуто без переназначения, начиная сif (!msg) return myfunc("Hello World");
, но это становится громоздким с несколькими аргументами.] В редких случаях, когда логика в функции должна заботиться о том, использовалась ли по умолчанию, я бы скорее обозначил специальное значение дозорного ( предпочтительно публично). – Beni Cherniavsky-Paskin 22 March 2015 в 13:44message
иmsg
. Но если он назвал бы это что-то вродеprocessedMsg
или что-то еще, что обеспечит дополнительный контекст - вероятность ошибки намного ниже. Сосредоточьтесь на том, что он говорит not i> on & quot; как & quot; он это говорит. ;) – alfasin 13 May 2016 в 22:10