Почему переменная Java чаще всего не объявляется как final? Сравните, чтобы ключевое слово было быстрым

В swift рекомендуется объявлять переменную с ключевым словом let, если переменная не изменяется после инициализации. Я вижу много переменных, объявленных как let.

Я думаю, что в java ключевое слово final может служить той же цели. Но из моего ограниченного опыта я вижу людей, объявляющих переменные как final только в редких случаях, например. ПИ.

Почему переменная Java чаще всего не объявляется как final? Что-то мне не хватает?


person Thor    schedule 01.07.2016    source источник
comment
Потому что это лишний набор текста, а программисты ленивы. Но если вы используете IDE, вероятно, у нее есть функция для добавления final, где это возможно, автоматически при сохранении файла.   -  person Thilo    schedule 01.07.2016
comment
Потому что люди ленивы. final требуется до Java 8 для замыканий, но кроме этого используется редко. Я и Роберт Симмонс-младший выступаем за более широкое распространение. Основная причина в том, что он отфильтровывает некоторые глупые опечатки во время компиляции. Но поскольку это не влияет на время выполнения программы, в отличие от const в C ++, нет достаточно веских (для многих) аргументов в пользу лишнего набора текста и шума кода.   -  person Boris the Spider    schedule 01.07.2016
comment
@Thilo, так что, как и ключевое слово let in swift, я должен объявить java-переменную final, где это возможно?   -  person Thor    schedule 01.07.2016
comment
Да, ты должен. Он четко указывает на ваше намерение (нежелание случайно изменить значение). Каждое намерение, которое вы сообщаете компилятору, помогает отловить ошибки (тот же аргумент, что и для @Override - вероятно, должен быть обязательным и / или ключевым словом, но сейчас уже слишком поздно, язык уже отсутствует).   -  person Thilo    schedule 01.07.2016
comment
Обратите внимание: это не совсем хороший вопрос; вы в основном спрашиваете о мнениях. Мои два цента: вы хотите сделать как можно больше полей (статических или нестатических) окончательными; но я лично не занимаюсь тем, чтобы помещать final в параметры метода или локальные переменные.   -  person GhostCat    schedule 01.07.2016
comment
Каждый раз, когда я помещаю final перед переменной, IDE сообщает мне, что мне нужно инициализировать его в конструкторах. Что произойдет, если для инициализации этой переменной потребуются относительно сложные вычисления, которые выполняются в методе, но после инициализации никогда не изменяются? Должен ли я вызывать этот метод вычисления внутри конструктора, чтобы инициализировать переменную, помеченную как final? Можно ли вызвать метод до завершения инициализации? (У меня более быстрый фон)   -  person Thor    schedule 01.07.2016
comment
Если вы используете переменную, которая должна быть изменяемой, почему вы должны использовать ключевое слово final для ее объявления?   -  person RockOnGom    schedule 01.07.2016
comment
@ Jägermeister: Что ж, для полей большинство разработчиков согласятся, что полезно использовать final. Но по поводу параметров и локальных переменных разные разработчики придерживаются разных мнений. Поэтому ответ на этот вопрос не обязательно о мнениях, а в том, чтобы указать на то, что существуют разные мнения.   -  person user140547    schedule 01.07.2016
comment
@RockOnGom Вообще говоря: компоненты, которые полагаются на неизменяемые штуки, имеют много преимуществ по сравнению с теми, которые позволяют изменять штуки. Таким образом, следует склоняться к проектам, которые работают с неизменяемыми переменными, полями и т. Д. Вы знаете, есть языки программирования, которые никогда не позволяют вам изменять существующую сущность, вместо этого вы в конечном итоге создаете новые сущности, которые несут измененные значения.   -  person GhostCat    schedule 01.07.2016


Ответы (6)


см. Следует ли в Java использовать final для параметров и локальных переменных, даже если мне это не нужно?

В основном для полей это полезно, а также изменяет их свойства параллелизма. см. Параллелизм Java: последнее поле (инициализируется в конструкторе) потокобезопасный?

Однако для локальных переменных и параметров значение final менее понятно. Он имеет некоторую семантическую ценность, но, с другой стороны, это также может быть шумом, если

public void foo (final int x, final int y){
    try{
        final int z = x+y;
    }
    catch (final Exception z){
        final String message = "";
        throw new RuntimeException(message);
    }
}

по сравнению с

public void foo (int x, int y){
    try{
        int z = x+y;
    }
    catch ( Exception z){
        String message = "";
        throw new RuntimeException(message);
    }
}

Если у вас есть короткие методы (которые обычно должны быть), то в любом случае очевидно, что переменные не меняются.

Поэтому некоторые разработчики предпочитают использовать final из-за его семантического значения, в то время как другие предпочитают не использовать его из-за его многословности.

person user140547    schedule 01.07.2016
comment
в то время как другие предпочитают не использовать его из-за его многословности. Для многих это относится к Java в целом :-) - person Thilo; 01.07.2016
comment
@Thilo: Что ж, правда, но поскольку Java уже довольно многословна, вам не нужно делать ее еще более многословной, когда в этом нет необходимости :) - person user140547; 01.07.2016

Java следует традиционному стилю мышления C: если мы что-то создаем (примитивные типы или объекты), по умолчанию это переменная, и вам нужно поставить «final» в java и «const» в C / C ++, чтобы сделать его константой. Swift является очень новым по сравнению с этими языками, и его цели - безопасные шаблоны программирования и простота. Если вы приобретете дополнительный опыт работы с Java, вы узнаете, что люди действительно чаще используют окончательные и лучшие практики. Основная причина, по которой я думаю (как вы также упомянули), заключается в том, что вы мало знакомы с Java.

person Khurram Shehzad    schedule 01.07.2016

Почему переменная Java чаще всего не объявляется как final? Что-то мне не хватает?

Вам не хватает «человеческой природы».

Просто синтаксис Java позволяет НЕ добавлять final. И вообще люди этого не делают, потому что этого легче не делать.

Обратите внимание, что проектное решение «переменные не являются окончательными по умолчанию» исходит от предков Java.


Конечно, это не отвечает на ваш подразумеваемый вопрос о том, должны ли программисты Java должны использовать final чаще 1. Но это вопрос личного мнения, и StackOverflow не одобряет основанные на мнении вопросы и ответы.

1 - .... в контекстах, где это было бы целесообразно. Использование final там, где переменная явно должна быть изменяемой, контрпродуктивно.

person Stephen C    schedule 01.07.2016
comment
Это также относится к классам и методам, которые, по мнению некоторых, должны быть final по умолчанию. - person shmosel; 01.07.2016
comment
Да ... хотя это другая проблема. Здесь вы столкнулись с проблемой поломки абстракции из-за наследования. - person Stephen C; 01.07.2016
comment
@shmosel Вы должны объявлять методы final, где это возможно (если вы не переопределяете его). В противном случае они по умолчанию являются виртуальными, что приводит к потере производительности. - person Xiaojun Chen; 01.07.2016
comment
@StephenC, не могли бы вы рассказать мне, где я могу задать вопросы и ответы, основанные на таком мнении, связанные с программированием? - person Thor; 01.07.2016
comment
@XiaojunChen - Это неверно. Этим занимается JIT-компилятор. - person Stephen C; 01.07.2016
comment
Нигде на StackExchange :-) Это не дискуссионное сообщество. - person Stephen C; 01.07.2016
comment
@Stephen C Я думаю, лучше явно объявить это, чем позволить компилятору разобраться в этом сам. Или в очень редких случаях люди не используют Oracle JVM :-) - person Xiaojun Chen; 01.07.2016
comment
Я не согласен. Загромождать код сомнительными намеками компилятору - плохая идея. Это делает ваш код менее гибким, менее читаемым, сложным в обслуживании и т. Д. (Как в старые плохие времена, когда некоторые программисты на C чрезмерно использовали ключевое слово register ... до тех пор, пока разработчики компилятора C не решили сделать компилятор игнорировать ключевое слово!) - person Stephen C; 01.07.2016

Инициализируйте переменную с final в Java allow compiler гарантирует, что вы можете инициализировать ее только один раз. Если это примитивный тип, такой как int или doubles, он может гарантировать, что значение не может измениться. Однако для Object final относится только к самой ссылке, а не к содержимому объекта, на который ссылаются. Это не дает никаких гарантий, что значения внутри упомянутого объекта останутся неизменными.

Например, я могу определить список с final следующим образом:

final List<String> foo = new ArrayList<String>();

Вышеупомянутый List foo не может быть инициализирован снова, но его содержимое может быть изменено, т.е. оно не делает foo неизменяемым. Следовательно, это делает ключевое слово final менее полезным.

Ключевое слово final имеет свое место при объявлении постоянного значения, особенно если нужен только один экземпляр в классе с использованием ключевого слова static. Ниже приведен пример в java.util.Random.Math:

public final class Math {

    public static final double PI = 3.14159265358979323846;
person Wilson    schedule 01.07.2016

Я думаю, это потому, что в Java нет такой «традиции».

Видите ли, в первой книге, которую я прочитал о Swift (язык программирования Swift 2.0 от Apple Inc.), говорится, что каждая создаваемая вами переменная, которая не изменяется, должна быть объявлена ​​как константа let.

Поскольку Swift Programming Language 2.0 (книга) является официальным руководством по Swift, почти все следят за ним. Даже если люди не читают эту книгу, они будут читать руководства, написанные людьми, которые читали эту книгу. В результате у всех такой стиль программирования.

Напротив, первая книга, которую я прочитал о Java (Programming with Java for Dummies), не подчеркивает, что мы должны использовать final, если значение не изменится. И в официальных документах это тоже не редкость. Так что этому правилу следуют лишь немногие программисты. В результате большинство из них пишет код, который действительно следует этому правилу.

Кроме того, вы должны написать еще 5 символов (слово «final» плюс пробел), чтобы объявить константу в Java, тогда как в Swift вы не пишете никаких дополнительных символов (var и let имеют такое же количество символов) ! Программисты ленивы, понимаете.

person Sweeper    schedule 01.07.2016

По крайней мере, исходя из моего опыта, мне сказали, что рекомендуется использовать final, если переменная не изменяется после запуска. Для примитивного типа JVM будет рассматривать его как постоянный и выполнять некоторую оптимизацию.

В других случаях, например, в Java, все методы по умолчанию являются виртуальными, если не объявлено final. Это также повысит производительность вычислений.

person Xiaojun Chen    schedule 01.07.2016