Ответ 1
Вы создаете огромное множество различных концепций. Даже вопрос в названии не соответствует вопросу в теле.
В любом случае, это те концепции, которые вы смешиваете:
- Переменные
- конечные переменные
- поля
- окончательные поля
- статические поля
- конечные статические поля
Ключевое слово static
имеет смысл только для полей, но в коде, который вы показываете, вы пытаетесь использовать его внутри функции, где вы не можете объявлять поля (поля являются членами классов, переменные объявляются в методах).
Попробуйте быстро описать их.
-
переменные объявляются в методах и используются как некоторая изменяемая локальная память (
int x; x = 5; x++
) -
конечные переменные также объявляются в методах и используются как неизменяемое локальное хранилище (
final int y; y = 0; y++; // won't compile
). Они полезны для обнаружения ошибок, когда кто-то пытается изменить что-то, что не должно быть изменено. Я лично делаю большинство параметров локальных переменных и методовfinal
. Кроме того, они необходимы, когда вы ссылаетесь на них из внутренних, анонимных классов. В некоторых языках программирования единственным видом переменной является неизменяемая переменная (в других языках переменная типа по умолчанию является неизменяемой переменной) - как упражнение, попытайтесь выяснить, как написать цикл, который будет запускать указанное количество раз, когда вам не разрешено ничего менять после инициализации! (попробуйте, например, решить fizzbuzz только с конечными переменными!). -
поля определяют изменяемое состояние объектов и объявляются в классах (
class x { int myField; }
). -
конечные поля определяют неизменяемое состояние объектов, объявляются в классах и должны быть инициализированы до завершения конструктора (
class x { final int myField = 5; }
). Они не могут быть изменены. Они очень полезны при многопоточности, поскольку у них есть специальные свойства, связанные с обмениванием объектов между потоками (вам гарантируется, что каждый поток увидит правильно инициализированное значение конечных полей объекта, если объект разделяется после завершения конструктора и даже если он разделяется с расчетом данных). Если вы хотите другое упражнение, попробуйте снова разрешить fizzbuzz, используя только конечные поля и другие поля, а не переменные или параметры метода (очевидно, вам разрешено объявлять параметры в конструкторах, но это все!). -
статические поля распределяются между всеми экземплярами любого класса. Вы можете думать о них как о каком-то глобальном изменяемом хранилище (
class x { static int globalField = 5; }
). Наиболее тривиальным (и обычно бесполезным) примером является подсчет экземпляров объекта (т.е.class x { static int count = 0; x() { count++; } }
, здесь конструктор увеличивает счетчик каждый раз, когда он вызывается, т.е. Каждый раз, когда вы создаете экземплярx
сnew x()
). Остерегайтесь того, что, в отличие от конечных полей, они по сути не являются потокобезопасными; другими словами, вы наверняка получите неправильное количество экземпляровx
с приведенным выше кодом, если вы создаете экземпляр из разных потоков; чтобы сделать это правильно, вам придется добавить какой-то механизм синхронизации или использовать для этой цели какой-то специализированный класс, но это другой вопрос (на самом деле это может быть предметом целой книги). -
конечные статические поля - глобальные константы (
class MyConstants { public static final double PI = 3.1415926535897932384626433; }
).
Есть много других тонких характеристик (например: компиляторы могут свободно заменять ссылки на конечное статическое поле на свои значения напрямую, что делает отражение бесполезным в таких полях, конечные поля могут быть фактически изменены с отражением, но это очень ошибка склонны и т.д.), но я бы сказал, что вам предстоит пройти долгий путь, прежде чем рыть дальше.
Наконец, есть и другие ключевые слова, которые могут использоваться с полями, такими как transient
, volatile
и уровни доступа (public
, protected
, private
). Но это другой вопрос (на самом деле, если вы хотите спросить о них, многие другие вопросы, я бы сказал).