Разное

Java статические переменные – Ключевое слово static в Java

Курс Java Syntax — Лекция: Статические переменные и методы

— Новая интересная тема. Хочу рассказать тебе о статических переменных и методах.

— О, я уже слышал про статические переменные. И про статические методы, кажется. Но хотелось бы больше подробностей.

— Когда мы описываем переменные в классе, мы указываем, будут ли эти переменные созданы всего один раз или же нужно создавать их копии для каждого объекта. По умолчанию создаётся новая копия переменной для каждого объекта. Вот как это выглядит:

Объявление класса

class Cat                        
{
    String name;                 

    Cat(String name)             
    {
        this.name = name;        
    }
}

Код в методе main:

Cat cat1 = new Cat("Vaska"); 
Cat cat2 = new Cat("Murka"); 
System.out.println(cat1.name);
System.out.println(cat2.name);

Вывод на экран будет таким:

Vaska
Murka

— Переменные cat1.name и cat2.name, хоть и описаны в одном классе – Cat, но хранят разные значения, т.к. привязаны к разным объектам.
— Это понятно.
— Статические же переменные – существуют в одном экземпляре, и обращаться к ним нужно по имени класса (внутри класса к статической переменной можно обращаться просто по имени):

Объявление класса

class Cat                   
{
    String name;            
    static int catCount;    

    Cat(String name)
    {
        this.name = name;
        Cat.catCount++;   
    }
}

Код в методе main:

System.out.println(Cat.catCount);
Cat cat1 = new Cat("Vaska");

System.out.println(Cat.catCount);
Cat cat2 = new Cat("Murka");

System.out.println(cat1.name);
System.out.println(cat2.name);
System.out.println(Cat.catCount);

Вывод на экран будет таким:

0
1
Vaska
Murka
2

— Это тоже понятно.

— Методы класса тоже делятся на две категории. Обычные методы вызываются у объекта и имеют доступ к данным этого объекта. Статические методы не имеют такого доступа – у них просто нет ссылки на объект, они способны обращаться либо к статическим переменным этого класса либо к другим статическим методам.

— Статические методы не могут обращаться к нестатическим методам или нестатическим переменным!

— А почему?

— Каждая обычная переменная класса находится внутри объекта. Обратиться к ней можно только имея ссылку на этот объект. В статический метод такая ссылка не передается.

— А в обычные методы передается?

— Да, в обычные методы передается, неявно. В каждый метод неявно передается ссылка на объект, у которого этот метод вызывают. Переменная, которая хранит эту ссылку, называется this. Таким образом, метод всегда может получить данные из своего объекта или вызвать другой нестатический метод этого же объекта.

— В статический метод вместо ссылки на объект передается null. Поэтому он не может обращаться к нестатическим переменным и методам – у него банально нет ссылки на объект, к которому они привязаны.

— Ясно.

— Так работают обычные нестатические методы:

Как выглядит код

Cat cat = new Cat();
String name = cat.getName();
cat.setAge(17);
cat.setChildren(cat1, cat2, cat3);

Что происходит на самом деле

Cat cat = new Cat();
String name = Cat.getName(cat);
Cat.setAge(cat, 17);
Cat.setChildren(cat, cat1, cat2, cat3);
При вызове метода в виде «объект» точка «имя метода», на самом деле вызывается метод класса, в который первым аргументом передаётся тот самый объект. Внутри метода он получает имя this. Именно с ним и его данными происходят все действия.

— А вот как работают статические методы:

Как выглядит код

Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount();

Что происходит на самом деле

Cat cat1 = new Cat();
Cat cat2 = new Cat();
int catCount = Cat.getAllCatsCount(null);
При вызове статического метода, никакого объекта внутрь не передаётся. Т.е. this равен null, поэтому статический метод не имеет доступа к нестатическим переменным и методам (ему нечего неявно передать в обычные методы).

— Переменная или метод являются статическими, если перед ними стоит ключевое слово static.

— А зачем такие методы нужны, если они так сильно ограничены?

— У такого подхода тоже есть свои преимущества.

— Во-первых, для того, чтобы обратиться к статическим методам и переменным не надо передавать никакую ссылку на объект.

— Во-вторых, иногда бывает нужно, чтобы переменная была в единственном экземпляре. Как, например, переменная System.out (статическая переменная out класса System).

— И в третьих, иногда нужно вызвать метод, еще до того, как будет возможность создавать какие-то объекты

— Это когда же?

— А почему, по-твоему, метод main объявлен статическим? Чтобы его можно было вызвать сразу после загрузки класса в память. Еще до того, когда можно будет создавать какие-то объекты.

javarush.ru

Переменные в Java 8 — urvanov.ru

Цикл статей «Учебник Java 8».

Следующая статья — «Java 8 операции».
Предыдущая статья — «Введение в Java 8».

Содержание

Типы переменных

Соглашение об именовании переменных

Типы данных

Значения по умолчанию

Литералы

— Целочисленные литералы

— Литералы с плавающей точкой

— Символьные и строковые литералы

— Другие литералы

Массивы

Типы переменных

Соглашение об именовании переменных

Типы данных

Значения по умолчанию

Литералы

— Целочисленные литералы

— Литералы с плавающей точкой

— Другие литералы

Массивы

Типы переменных

Соглашение об именовании переменных

Типы данных

Значения по умолчанию

Литералы

— Целочисленные литералы

— Литералы с плавающей точкой

— Символьные и строковые литералы

— Другие литералы

Массивы

Синтаксис объявления переменных в Java следующий:

int ammoCount; int weight = 80;

int ammoCount;

int weight = 80;

Сначала идёт тип переменной, в данном случае int, затем имя переменной ( ammoCount и weight), затем может идти (но не обязательно) инициализация переменной начальным значением. В примере выше объявлено две переменные: ammoCount  и weight. Обе переменные имеют тип int. Переменная weight инициализирована начальным значением 80.

Типы переменных

В Java есть четыре типа переменных:

  • Переменные экземпляров (Не статические свойства/поля) или Instance Variables (Non-Static Fields). Это те переменные, которые объявлены внутри класса без ключевого слова static . Их значения отличны для каждого экземпляра класса.
  • Переменные класса (Статические свойства/поля) или Class Variables (Static Fields). Это любое свойство класса, объявленное  с ключевым словом static. Это свойство относится к самому классу, а не к его экземплярам. Оно существует всегда в единственном экземпляре.
  • Локальные переменные
    или Local Variables. Локальные переменные — это переменные, объявленные внутри метода (внутри фигурных скобок метода). Они доступны только внутри метода, в котором они объявлены. В них методы хранят информацию, необходимую только им, например промежуточные значения своих вычислений.
  • Параметры или Parameters. Параметры — это переменные, которые принимают значение переданных аргументов метода. Мы уже видели пример параметров в описании метода  public static void main(String[] args). В этом описании метода args  — параметр метода. Советую также прочитать статьи «Формальные параметры» и «Фактические параметры».

Соглашение об именовании переменных

В языке программирования Java существуют следующие соглашения о именовании переменных:

  • Имена переменных зависят от регистра. Переменные var1 и VAR1 — это две разные переменные. Длина имени переменной не ограничена, оно может содержать любое количество букв Юникода и цифр, может начинаться с буквы, знака доллара «$» или символа подчёркивания «_». Однако согласно соглашению о кодировании в Java имена переменных всегда должны начинаться со строчной буквы английского алфавита, но не с символа «$» или «_». Также согласно соглашению знак доллара не используется совсем. Некоторые утилиты могут генерировать имена переменных с символом доллара, но вы не должны его использовать.
  • Последующие символы могут быть буквами, цифрами, знаком доллара и подчёркивания. Рекомендуется использовать полные английские слова при именовании переменных, а не сокращения.
  • Если имя переменной содержит несколько слов, то первые буквы второго и последующего слова делаются прописными, например energyUsed, moneyFoundOnStreets, abstractProxyFactorySingletonBean.
  • Нельзя использовать зарезервированные (или ключевые) слова в качестве имён переменных.
  • Если значение переменной никогда не меняется, например static final int BUFFER_SIZE=1024;, то согласно соглашению нужно каждую букву делать ЗАГЛАВНОЙ, а между словами использовать символ подчёркивания «_».

Язык программирования Java является строго типизированным языком. Каждая переменная должна быть объявлена перед использованием с указанием своего типа, имени и, возможно, начального значения.

Типы данных

В Java имеется восемь примитивных типов данных:

  • byte — 8-и битное знаковое число. Может хранить значения от -128 до +127 (включительно). Используется, например в массивах, когда нужно сэкономить память.
  • short — 16-и битное знаковое число. Может хранить значения от -32 768 до +32 767 (включительно). Используется вместо int, когда необходимо сэкономить память.
  • int — 32-х битное знаковое число. Может хранить значения от -231 до 231-1. В Java 8 можно использовать этот тип для хранения беззнакового целого числа от 0 до 2
    32
    -1, используя методы compareUnsigned, divideUnsigned и другие из класса java.lang.Integer.
  • long — 64-х битное знаковое число.Может хранить значения от -263 до 263-1. В Java 8 можно использовать этот тип для хранения беззнакового целого числа от 0 до 264-1, используя методы compareUnsigned, divideUnsigned и другие из класса java.lang.Long.
  • float — 32-битное число с плавающей точкой одинарной точности согласно IEEE 754. Используется вместо double, когда нужно сэкономить память. Нельзя использовать float  для хранения и обработки денежных значений. Для денежных значений нужно использовать java.math.BigDecimal.
  • double — 64-битное число с плавающей точкой двойной точности согласно IEEE 754. Используется при необходимости хранить дробные значения. Нельзя использовать double  для хранения и обработки денежных значений. Для денежных значений нужно использовать java.math.BigDecimal.
  • boolean — логическое значение. Имеет только два возможных значения: true  и false. Используется для флагов. Его размер точно не определён, несмотря на то что он несёт 1 бит полезной информации.
  • char — 16-и битный символ Юникода. Его минимальное значение ‘\u0000’ или 0, а максимальное ‘\uffff’ (65 535 включительно)

Значения по умолчанию

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

С полями классов ситуация несколько иная. Если поле класса (не важно статическое или нет) не инициализировано каким-нибудь значением, то ему будет присвоено значение по умолчанию. Значение по умолчанию — это null  или 0 соответствующего типа.

Следующая таблица показывает соответствие типа данных и значения по умолчанию:

Тип данныхЗначение по умолчанию для полей
byte0
short0
int0
long0L
float0.0f
double0.0d
char‘\u0000’
String (или любой объект)null
booleanfalse

Литералы

Литерал — это запись в исходном коде, представляющая собой фиксированное значение.

Можно присвоить литерал переменной примитивного типа:

boolean b = true; char ch2 = ‘f’; int i1 = 100000; byte b1 = 100; short sh2 = 10000;

boolean b = true;

char ch2 = ‘f’;

int i1 = 100000;

byte b1 = 100;

short sh2 = 10000;

Целочисленные литералы

Целочисленный литерал имеет тип int  в обычном случае и тип long, если заканчивается на символ «l» (строчная буква «эл» английского алфавита) или «L» (прописная буква «эл» английского алфавита). Рекомендуется использовать «L», так как «l» трудно отличить от единицы.

Значения типов byte, short, int  и long  могут быть созданы из литералов типа int. Значения типа long, превышающие int, могут быть созданы из литералов типа long.

Десятичные литеры могут быть записаны в четырёх системах счисления:

  • Десятичной. По основанию 10. Цифры от 0 до 9. Эту систему счисления мы используем каждый день.
  • Шестнадцатеричной. По основанию 16. Цифры от 0 до 9 и буквы от A до F. Префикс 0x.
  • Восьмеричной. По основанию 8. Цифры от 0 до 7. Префикс цифра 0.
  • Двоичной. По основанию 2. Цифры от 0 до 1. Начиная с Java SE 7. Префикс 0b.

Пример:

// Число 41 в десятичной системе int v1 = 41; // Число 41 в шестнадцатеричной системе int v2 = 0x29; // Число 41 в восьмеричной системе счисления int v3 = 051; // Число 41 в двоичной системе int v3 = 0b101001;

// Число 41 в десятичной системе

int v1 = 41;

//  Число 41 в шестнадцатеричной системе

int v2 = 0x29;

// Число 41 в восьмеричной системе счисления

int v3 = 051;

// Число 41 в двоичной системе

int v3 = 0b101001;

Можно использовать символ подчёркивания между любыми двумя цифрами любой записи целочисленного литерала. Это может использоваться, например, для отделения групп цифр:

int v1 = 1_000_000; //1000000 int v2 = 0x3f_3f; //16191 int v3 = 0_5_1; //41 int v4 = 0b100_101_001;/

int v1 = 1_000_000; //1000000

int v2 = 0x3f_3f; //16191

int v3 = 0_5_1; //41

int v4 = 0b100_101_001;/

Но целочисленный литерал не может заканчиваться или начинаться символом подчёркивания, и символ подчёркивания не может стоять сразу после 0x или 0b у шестнадцатеричной и двоичной системы счисления.

Литералы с плавающей точкой

Литералы с плавающей точкой имеют тип float, если они оканчиваются на «f» или «F», и тип double, если они не имеют окончания или оканчиваются на «d» или «D».

Можно также использовать научную запись числа с помощью «e» или «E», что означает экспоненту (умножить на 10 в степени указанного числа).

double d1 = 123.4; // То же значение, что и у d1 (1.234 умножить 10 во второй степени) double d2 = 1.234e2; float f1 = 123.4f;

double d1 = 123.4;

// То же значение, что и у d1 (1.234 умножить 10 во второй степени)

double d2 = 1.234e2;

float f1  = 123.4f;

Существует также двоично-десятичная запись:

// 1 (в шестнадцатеричной системе) умножить на 2 в степени 3. // То есть 8.0 double d1 = 0x1p3 // 0xF (в шестнадцатеричной системе) умножить на 2 в степени 3 // То есть 120.0 double d2 = 0xFp3;

// 1 (в шестнадцатеричной системе) умножить на 2 в степени 3.

// То есть 8.0

double d1 = 0x1p3

 

// 0xF (в шестнадцатеричной системе) умножить на 2 в степени 3

// То есть 120.0

double d2 = 0xFp3;

Можно использовать символ подчёркивания для отделения групп в целой части, дробной части и экспоненте (после «e» или «E», «p» или «P»). Символ подчёркивания может стоять только между двумя цифрами!

Примеры:

double d1 = 1_000.000_001;// 1000.000001

double d1 = 1_000.000_001;// 1000.000001

Символьные и строковые литералы

Строковые и символьные литералы могут содержать любой символ Юникода (UTF-16).  Если ваш редактор текста не поддерживает эти символы, то вы можете вставлять их коды вида ‘\u00A9’ (знак копирайта), где после \u стоит код символа Юникод в шестнадцатеричной системе счисления. Строки всегда заключаются в двойные кавычки, а символы — в одинарные.

Можно также использовать коды \b  (backspace), \t  (табуляция), \n  (подача строки), \f  (конец страницы, такое сейчас почти не используется), \r  (возврат каретки), \»  (двойная кавычка), \’  (одинарная кавычка) и  \\  (косая черта).

Другие литералы

Существует ещё литерал null, которые можно присвоить для ссылочных типов данных.

Плюс ещё есть литерал класса. Он формируется с помощью добавления .class  к имени типа, например String.class. Этот литерал ссылается на объект java.lang.Class, который представляет собой тип.

 

Массивы

Массив — это объект-контейнер, хранящий фиксированное количество элементов одинакового типа. Длина массива фиксируется после создания и не меняется во всём времени существования этого массива.

Нумерация элементов массива начинается с нуля. Первый элемент имеет индекс 0, второй — 1 и так далее. Последний элемент имеет индекс на единицу меньший длины массива.

При объявлении массива сначала указывается тип данных, затем квадратные скобки и имя переменной. Квадратные скобки можно ставить не только после типа данных, но и после имени переменной, однако рекомендуется первый вариант.

Пример:

int[] arrayOfInt; int arrayOfInt2[]; long[] arrayOfLong; String[] arrayOfString; double[] arrayOfDouble;

int[] arrayOfInt;

int arrayOfInt2[];

long[] arrayOfLong;

String[] arrayOfString;

double[] arrayOfDouble;

Для инициализации массива используется оператор new  и имя типа данных с указанием размерности в квадратных скобках:

int a[] = new int[10]; // массив из 10 элементов типа int. double[] arrayOfDouble = new double[12]; // массив из 12 элементов типа double.

int a[] = new int[10]; // массив из 10 элементов типа int.

double[] arrayOfDouble = new double[12]; // массив из 12 элементов типа double.

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

urvanov.ru

java — Почему статические переменные считаются злыми?

Если вы используете ключевое слово static без ключевого слова final, это должно быть сигналом для тщательного рассмотрения вашего дизайна. Даже наличие «финала» не является бесплатным пропуском, поскольку изменчивый статический конечный объект может быть столь же опасным.

Я бы оценил где-то около 85% времени, когда я вижу «статический без» финала, это НЕПРАВИЛЬНО. Часто я нахожу странные обходные пути для маскировки или скрытия этих проблем.

Пожалуйста, не создавайте статические переменные. Особенно коллекции. В общем случае коллекции должны быть инициализированы, когда их содержащий объект инициализируется и должен быть сконструирован таким образом, чтобы они были reset или забыты о том, когда их содержащий объект забыт.

Использование статики может создавать очень тонкие ошибки, которые вызовут поддерживающие инженеры дни боли. Я знаю, потому что я и создал, и охотился на эти ошибки.

Если вы хотите получить более подробную информацию, пожалуйста, прочитайте…

Почему не использовать статику?

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

Код, который опирается на статические объекты, может быть легко проверен модулем, а статика не может быть легко издевается (обычно).

Если вы используете статику, невозможно выполнить замену реализации класса, чтобы проверить компоненты более высокого уровня. Например, представьте себе статический CustomerDAO, который возвращает объекты Customer, которые он загружает из базы данных. Теперь у меня есть класс CustomerFilter, которому нужно получить доступ к некоторым объектам Customer. Если CustomerDAO является статическим, я не могу написать тест для CustomerFilter без предварительной инициализации моей базы данных и заполнения полезной информации.

И заселенность базы данных и инициализация занимает много времени. И, по моему опыту, ваша база инициализации базы данных будет меняться со временем, то есть данные будут морфироваться, а тесты могут нарушиться. IE, представьте, что Клиент 1 был VIP, но каркас инициализации DB изменился, и теперь Клиент 1 больше не VIP, но ваш тест был жестко запрограммирован для загрузки Customer 1…

Лучший подход — создать экземпляр CustomerDAO и передать его в CustomerFilter, когда он будет создан. (Еще лучше было бы использовать Spring или другую структуру инверсии управления.

Как только вы это сделаете, вы можете быстро высмеять или заглушить альтернативный DAO в своем CustomerFilterTest, что позволит вам получить больше контроля над тестом,

Без статического DAO тест будет быстрее (без инициализации db) и более надежным (потому что он не сработает при изменении кода инициализации db). Например, в этом случае обеспечение клиента 1 будет и всегда будет VIP, насколько это касается теста.

Выполнение тестов

Статика вызывает настоящую проблему при совместном выполнении наборов единичных тестов (например, с сервером Continuous Integration). Представьте себе статическую карту сетевых объектов Socket, которые остаются открытыми с одного теста на другой. Первый тест может открыть Socket на порту 8080, но вы забыли очистить карту, когда тест разорвется. Теперь, когда запускается второй тест, он может сбой, когда пытается создать новый Socket для порта 8080, поскольку порт все еще занят. Представьте также, что ссылки Socket в вашей статической коллекции не удаляются, и (за исключением WeakHashMap) никогда не могут быть собраны мусором, что вызывает утечку памяти.

Это обобщенный пример, но в больших системах эта проблема происходит ВСЕ ВРЕМЯ. Люди не думают о модульных тестах, которые запускают и останавливают свое программное обеспечение повторно в одной JVM, но это хороший тест вашего программного обеспечения, и если у вас есть стремления к высокой доступности, то это то, о чем вам нужно знать.

Эти проблемы часто возникают с объектами инфраструктуры, например, вашими доступами к БД, кэшированием, сообщениями и протоколированием. Если вы используете Java EE или некоторые из лучших в своем классе фреймворков, они, вероятно, справятся с этим много, но если вы, как я, имеете дело с унаследованной системой, у вас может быть много настраиваемых фреймворков для доступа к этим слоям.

Если системная конфигурация, применяемая к этим компонентам инфраструктуры, изменяется между модульными тестами, а структура unit test не срывает и не восстанавливает компоненты, эти изменения не могут вступить в силу, и когда тест основывается на этих изменениях, они потерпят неудачу.

К этой проблеме относятся даже неструктурные компоненты. Представьте себе статическую карту под названием OpenOrders. Вы пишете один тест, который создает несколько открытых ордеров, и проверяет, чтобы все они находились в правильном состоянии, затем тест заканчивается. Другой разработчик пишет второй тест, который помещает заказы, необходимые ему в карту OpenOrders, а затем утверждает, что количество заказов является точным. Выполняйте индивидуально, эти тесты будут проходить, но при запуске вместе в пакете они потерпят неудачу.

Хуже того, отказ может быть основан на порядке, в котором выполнялись тесты.

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

Тонкие ошибки

Если вы работаете в среде с высокой степенью доступности или где-либо, где эти потоки могут быть запущены и остановлены, такая же проблема, о которой упоминалось выше, с помощью unit test suite может применяться, когда ваш код также работает на производстве.

При работе с потоками вместо использования статического объекта для хранения данных лучше использовать объект, инициализированный на этапе запуска потоков. Таким образом, каждый раз, когда поток запускается, создается новый экземпляр объекта (с потенциально новой конфигурацией), и вы избегаете данных из одного экземпляра потока, истекающего до следующего экземпляра.

Когда поток умирает, статический объект не получает reset или сбор мусора. Представьте, что у вас есть поток, называемый «EmailCustomers», и когда он запускается, он заполняет статическую коллекцию String списком адресов электронной почты и затем отправляет по электронной почте каждый из адресов. Допустим, что поток прерывается или отменяется каким-то образом, поэтому ваша платформа высокой доступности перезапускает поток. Затем, когда поток запускается, он перезагружает список клиентов. Но поскольку коллекция является статической, она может сохранить список адресов электронной почты из предыдущей коллекции. Теперь некоторые клиенты могут получать дубликаты писем.

Рядом: Статический Финал

Использование «статического финала» является фактически эквивалентом Java С#define, хотя существуют технические различия в реализации. C/С++ #define перед компиляцией выгружается из кода предварительным процессором. «Статический финал» Java будет содержать резидентную память в стеке. Таким образом, он больше похож на переменную «static const» в С++, чем на #define.

Резюме

Надеюсь, это поможет объяснить несколько основных причин, почему статика проблематична. Если вы используете современную Java-инфраструктуру, такую ​​как Java EE или Spring и т.д., Вы не можете столкнуться со многими из этих ситуаций, но если вы работаете с большим количеством устаревшего кода, они могут стать намного более частыми.

qaru.site

java — Разница между статической и конечной статической переменной в Java

Вы создаете огромное множество различных концепций. Даже вопрос в названии не соответствует вопросу в теле.

В любом случае, это те концепции, которые вы смешиваете:

  • Переменные
  • конечные переменные
  • поля
  • окончательные поля
  • статические поля
  • конечные статические поля

Ключевое слово 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). Но это другой вопрос (на самом деле, если вы хотите спросить о них, многие другие вопросы, я бы сказал).

Bruno Reis 04 нояб. ’11 в 5:342011-11-04 05:34 источник поделиться

qaru.site

java — Статические переменные и многопоточность в java

Проблема с потоковой передачей такова: «10 000-футовое» представление памяти Java состоит в том, что есть один блок памяти, который разделяется всеми классами, всеми объектами, всеми загрузчиками классов и всеми потоками в запущенной JVM — — все, что доступно с одного места в коде, доступно везде (с учетом соответствующей ссылки). Единственное исключение — это регистры и стеки выполнения, которые концептуально основаны на потоках.

Это хорошо работает с одним процессором, где потоки по очереди исполняются в одном наборе регистров и ALU и т.д. Но большинство современных компьютеров имеют несколько процессоров, поэтому несколько потоков могут выполняться буквально в одно и то же время. Если эти процессоры должны были ссылаться на одну и ту же физическую память, тогда (на основе реального опыта), вы могли бы получить только 1,5-кратное повышение производительности с 4-мя процессорами, и оно выродилось бы оттуда.

Итак, используется «кеш», так что каждый процессор имеет свою собственную небольшую частную копию бит и частей большей памяти. В большинстве случаев процессоры обращаются к совершенно другим областям памяти, поэтому это работает отлично, но иногда (как при работе с каким-то «общим» объектом) они должны «сражаться» над одним и тем же набором байтов.

Решение состоит в том, чтобы установить протоколы, чтобы ни один из двух процессоров не попытался изменить одни и те же места хранения в одно и то же время (или почти одинаковые) и гарантировать, что один из процессоров изменился, чтобы «сбросить» в основное хранилище, а другие процессоры узнали об изменениях и посоветовали перезагрузить их взгляд на измененные данные.

Но он (невероятно) неэффективен для этого после каждой операции (и, откровенно говоря, аппаратные дизайнеры в значительной степени уклонились от этой проблемы и больше наложили эту работу на программное обеспечение, чем это, вероятно, оправдано). Таким образом, схемы используются так, что сброс и перезагрузка данных происходит только на определенных «границах» или когда выполняются определенные специальные типы ссылок.

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

qaru.site

java — Статические переменные в С++ и Java

Статическое ключевое слово используется для почти той же цели как на С++, так и на Java. Однако есть некоторые отличия.

1) Статические члены данных: Как и С++, статические члены данных в Java являются членами класса и распределяются между всеми объектами.

2) Методы статических членов: Как и С++, методы, объявленные как статические, являются членами класса и имеют следующие ограничения:

  • (i) Они могут вызывать только другие статические методы.
  • (ii) Они должны получать только статические данные.
  • (iii) Они не могут получить доступ к this или super

Подобно С++, к элементам статических данных и статическим методам можно обращаться без создания объекта. К ним можно получить доступ, используя имя класса.

3) Статический блок: В отличие от С++, Java поддерживает специальный блок, называемый static block (также называемый static clause), который может использоваться для статической инициализации класса. Этот код внутри статического блока выполняется только один раз (при первом создании объекта этого класса или при первом доступе к статическому члену этого класса (даже если вы никогда не делаете объект этого класса)).

4) Статические локальные переменные: В отличие от С++, Java не поддерживает статические локальные переменные. Если используется, программа Java не работает в компиляции.

5) Статический класс: Классы также могут быть сделаны статическими в Java. В java мы не можем сделать класс верхнего уровня статическим. Только вложенные классы могут быть статическими.

  • Вложенный статический класс не нуждается в ссылке на класс Outer, но для нестатического вложенного класса или для класса Inner требуется ссылка на внешний класс.
  • Внутренний класс (или нестатический вложенный класс) может обращаться как к статическому, так и к нестатические члены класса Outer. Статический класс не может получить доступ нестатические члены класса Outer. Он может получить доступ только к статичным членов класса Outer.

    Ссылка: www.geeksforgeeks.org

источник поделиться

qaru.site

java — Статические переменные: хорошие или плохие?

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

Почему все труднее?

Это то, что все статические переменные.

В основном, они предоставляют общую точку доступа, к которой вы можете получить доступ из любого контекста (статический, программный, внешний).

Вы в основном заявляете, что входная дверь здесь, и она желтая. Кто-то, выглядывающий извне, увидит желтую дверь. Кто-то на внутренней ходьбе увидит дверь и станет желтой. Кто-то в комнате может смотреть в коридор и видеть, что он желтый.

И если вы нарисуете его красным, он будет хорошо виден всем.

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

возьмите, например,

class test {
public int ten = 10;
   public test() {
   }
}

Каждый раз, когда вы создаете new test(), для десяти переменных будет назначено целое число памяти. Поэтому, если у вас есть 10 тестовых экземпляров, у вас будет 10 отдельных целых чисел, имеющих одинаковое значение.

если у вас есть этот

class test {
public static int ten = 10;
   public test() {
   }
}

и у вас есть десять тестовых экземпляров, у вас будет только один целочисленный экземпляр десять. Это экономит память, сбор мусора. Хотя я только советую это для постоянных списков/переменных, которые не меняются, и вы можете позволить себе хранить в памяти неопределенно. Не делайте этого с каждой переменной. Сделайте это для больших вещей, как образ, который вы повторно используете снова и снова. Не рекомендуется хранить одно и то же изображение в памяти несколько раз.

Когда я изначально написал свой ответ, я не знал, как работают статические переменные. Я перепутал static final и static. По статическим переменным вы можете назначить новые значения. статические окончательные неизменяемы. они не могут быть изменены.

qaru.site

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *