Private Static

🛑 ALL INFORMATION CLICK HERE 👈🏻👈🏻👈🏻
Руководство по модификатору static в Java
Руководство по модификатору static в Java
В этой статье мы подробно рассмотрим, используемое в языке Java ключевое слово static : его применение к переменным, методам, блокам инициализации, вложенным классам (nested classes), а также, рассмотрим его влияние на них.
В языке программирования Java ключевым словом static помечают члены (поля или методы), которые принадлежат классу, а не экземпляру этого класса.
Это означает, что какое бы количество объектов вы не создали, всегда будет создан только один член, доступный для использования всеми экземплярами класса.
Ключевое слово static применимо к переменным, методам, блокам инициализации, импорту и вложенным классам (nested classes).
3. Статические поля (переменные класса)
В языке Java, если поле объявляется статическим (путем добавления модификатора static), то в независимости от количества созданных объектов класса — всегда будет существовать только один экземпляр статического поля. Значение такого поля будет единым и общим для всех объектов класса, содержащих это поле.
С точки зрения используемой памяти, статические переменные размещаются в специальном пуле в памяти JVM, называемом Metaspace (до Java 8 он назывался Permanent Generation или PermGen, который был полностью удален и заменен на Metaspace).
Предположим, у нас есть класс Car с несколькими атрибутами (полями). Каждый экземпляр данного класса будет иметь свою, отличающуюся от других копию этих переменных экземпляра. Значения таких полей можно менять в объектах независимо друг от друга.
А теперь предположим, что нам требуется переменная-счетчик для хранения количества созданных объектов Car, которая являлась бы общей для всех его экземпляров. При этом необходимо, чтобы каждый из них имел к ней доступ и мог изменять.
Тут-то нам и пригодится статическая переменная (в этом и последующих примерах все поля будут размещаться в порядке их инициализации при создании объекта):
public class Car {
static int numberOfCars;
private String name;
private String engine;
public Car (String name, String engine) {
this .name = name;
this .engine = engine;
numberOfCars++;
}
// getters and setters
}
Теперь для каждого объекта этого класса будет увеличиваться один и тот же экземпляр переменной numberOfCars . Давайте это проверим:
public class CarMain {
public static void main (String[] args) {
Car car1 = new Car( "Jaguar" , "V8" );
Car car2 = new Car( "Bugatti" , "W16" );
System.out.println( "Результат: " + Car.numberOfCars);
}
}
Результат: 2
В Java сериализация позволяет сохранить текущее состояние объекта в поток байтов таким образом, чтобы его можно было передать, например, через сеть. Но, т.к. статические переменные относятся к классу, то они не могут быть сериализованы и просто игнорируются.
Рассмотрим следующий пример (для простоты не используем геттеры и сеттеры) сериализации:
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1234567890l ;
static int age;
static transient String faculty;
String firstName;
transient boolean examPassed;
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class SerializationStudent {
public static void main (String[] args) {
Student student = new Student();
student.firstName = "Игорь" ;
student.examPassed = true ;
student.age = 22 ;
student.faculty = "Факультет авиационных и космических систем" ;
try (FileOutputStream fos = new FileOutputStream( "./out.txt" )) {
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(student);
System.out.println( "Данные сериализованы в out.txt" );
} catch (IOException e) {
e.printStackTrace();
}
}
}
Если запустить файл SerializationStudent.java , то в корне проекта появится файл out.txt, а в консоль будет выведено сообщение:
Теперь запустим файл DeSerializationStudent.java, который достанет из файла out.txt данные и десериализует их обратно в объект Student:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class DeSerializationStudent {
public static void main (String[] args) {
Student student = null ;
try (FileInputStream fis = new FileInputStream( "./out.txt" )) {
ObjectInputStream ois = new ObjectInputStream(fis);
student = (Student) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException c) {
System.out.println( "Класс Student не найден" );
c.printStackTrace();
return ;
}
System.out.println( "Десериализация объекта Student..." );
System.out.println( "Имя студента: " + student.firstName);
System.out.println( "Возраст студента: " + student.age);
System.out.println( "Экзамен сдан? " + student.examPassed);
System.out.println( "Факультет студента: " + student.faculty);
}
}
В консоль будет выведено следующее:
Как можно увидеть, только переменная firstName была сохранена, а остальные переменные получили значения по умолчанию .
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 1234567890l ;
static int age = 17 ;
static transient String faculty = "Факультет радиофизики" ;
public String firstName = "Катя" ;
transient boolean examPassed = true ;
}
Повторно запустим файл DeSerializationStudent.java и получим следующее:
Обратите внимание, и переменная age , и переменная faculty были успешно сериализованы и десериализованы. Для каждой переменной значения были взяты из класса Student , а не из объекта student . Кроме того, переменная faculty является не только static, она еще и transient (ключевым словом transient помечают переменные, состояние которых мы не хотим сериализовать / сохранить. Как раз из-за transient значение examPassed не было сериализовано). В данном случае модификатор static изменяет поведение этой переменной.
3.3 Причины использовать статические поля
Когда значение поля должно быть общим для всех объектов класса, в котором оно определено Когда значение поля не зависит от наличия объектов класса, в котором оно определено Когда значение поля может быть изменено из любого объекта класса, в котором оно определено
Статические переменные могут быть созданы только, как переменные класса. Они не могут быть локальными переменными (IDEA выдаст ошибку Modifier 'static' not allowed here или java: illegal start of expression ):
public class Main {
public static void main (String[] args) {
static String wrongVar = "Modifier 'static' not allowed here" ;
System.out.println(wrongVar);
}
}
К статическим полям класса можно получить доступ без создания объекта, используя имя класса (ссылка на объект не нужна)
В примере с классом Car присвоим 100 статической переменной numberOfCars:
public static int numberOfCars = 100 ;
А затем обратимся к этому полю через класс Car:
System.out.println( "Результат: " + Car.numberOfCars);
Результат: 100
Несмотря на то, что получить доступ к статическим полям можно с помощью ссылки на объект (например, car1.numberOfCars ), мы должны воздерживаться от её применения, поскольку в этом случае становится не совсем понятно, является ли эта переменная переменной экземпляра или же переменной класса. Вместо этого всегда необходимо ссылаться на статические переменные, используя имя класса (например, Car.numberOfCars )
// Рекомендуется
System.out.println( "Результат: " + Car.numberOfCars);
// Не рекомендуется, но работает
System.out.println( "Результат: " + car1.numberOfCars);
Статические поля не сериализуются (как и transient- переменные). При десериализации такие поля будут иметь значения по умолчанию , заданные JVM при создании объекта
Во время десериализации, значение статической переменной может быть выведено, если эта статическая переменная была определена при инициализации базового класса. Это означает, что статическая переменная будет проинициализирована с тем же самым значением, которое было при загрузке класса.
Если переменная определена как static и transient, то модификатор static управляет поведением переменной, а не transient. Если мы присвоили такой переменной значение во время загрузки класса, то это значение будет присвоено статической переменной во время десериализации.
4. Статические методы (методы классов)
Подобно статическим полям, статические методы также принадлежат классу, а не объекту, поэтому их можно вызывать без создания экземпляра класса, в котором они находятся. При этом следует помнить, что из статического метода можно получить доступ только к статическим переменным или к другим статическим методам.
public class Test {
int x;
public static void main (String[] args) {
x = 0 ;
}
}
В противном случае при компиляции будет выведена ошибка.
Ниже представлен утилитный метод sumOfInts , принимающий на вход последовательность целых чисел и возвращающий сумму этих чисел:
Статические методы обычно используются для выполнения операции, не зависящей от создания экземпляра. При этом, они широко используются для создания служебных (утилитных) или вспомогательных классов, поскольку их можно вызывать без создания нового объекта этих классов.
public class MathUtils {
public static int sumOfInts ( int i, int ...nums) {
int sum = i;
for ( int num : nums) {
sum += num;
}
return sum;
}
}
class Main {
public static void main (String[] args) {
System.out.println( "Результат: " + MathUtils.sumOfInts( 1 , 2 , 3 ));
}
}
Результат: 6
В JDK служебные классы активно используются: Collections , Math , Arrays ; StringUtils из Apache или CollectionUtils из Spring framework. Все методы этих классов являются статическими.
4.2 Статические методы в интерфейсах
В версии Java 8 появилась возможность определения статических методов в интерфейсах. Их поведение напоминает поведение методов по умолчанию (default methods), но есть существенные отличия – они не могут быть переопределены методами в реализующих интерфейс классах. Такая особенность позволяет избежать нежелательных результатов, которые возможны в случае некорректной реализации метода в классе.
Пример кода с использованием статического метода в интерфейсе:
public interface Arithmetic {
public static int multiply ( int a, int b ) {
return a * b;
}
}
class Main {
public static void main ( String[] args ) {
int result = Arithmetic.multiply( 2 , 3 );
System. out .println(result);
}
}
Результат: 6
Обратите внимание, что для использования статических методов интерфейса не нужно использовать ключевое слово « implements ». Достаточно (и это необходимо) использовать имя интерфейса вместе с именем статического метода. В других случаях, статические методы интерфейса видны только методам этого интерфейса.
4.3 Причины использовать статические методы
Для доступа / управления статическими переменными и другими статическими методами, которые не зависят от объектов Для служебных, вспомогательных классов и интерфейсов, поскольку не требуют создания объектов и соответственно, обеспечивают большую производительность Когда методу требуется доступ лишь к статическим полям класса
Статические методы в Java вызываются во время компиляции. Поскольку переопределение метода является частью полиморфизма во время выполнения ( Runtime Polymorphism ), статические методы не могут быть переопределены. Это справедливо также для статических методов интерфейса Абстрактные методы не могут быть статическими Статические методы не могут использовать ключевые слова this или super Методы экземпляра могут обращаться непосредственно как к методам экземпляра, так и к переменным экземпляра Методы экземпляра также могут непосредственно обращаться к статическим переменным и статическим методам Статические методы могут обращаться ко всем статическим переменным и другим статическим методам Статические методы не могут напрямую обращаться к переменным экземпляра и методам экземпляра. Для этого им нужна ссылка на объект Статические поля и методы не являются потокобезопасными. Т.к. каждый экземпляр класса имеет одну и ту же копию статической переменной, такая переменная нуждается в защите от одновременного обращения к ней нескольких потоков. Для этого статическая переменная должна быть синхронизирована Статические методы связываются во время компиляции, в отличие от не статических методов, которые связываются во время исполнения. Из-за этого статические методы не могут быть переопределены, т.к. полиморфизм во время выполнения не распространяется на них. Если объявить в классе-наследнике метод с таким же именем и сигнатурой, то он лишь перекроет (hiding methods) метод из суперкласса вместо его переопределения. При обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызываться метод исходя из типа переменной. В этом есть смысл, только тогда, когда нет возможности или необходимости переопределения такого метода классами-наследниками.
public class SuperClass {
public static void staticMethod ( ) {
System. out .println( "SuperClass: внутри статического метода" );
}
public void notStaticMethod ( ) {
System. out .println( "SuperClass: внутри не статического метода" );
}
}
class SubClass extends SuperClass {
//Попытка "переопределения" статического метода
public static void staticMethod ( ) {
System. out .println( "SubClass: внутри статического метода" );
}
// переопределение не статического метода
public void notStaticMethod ( ) {
System. out .println( "SubClass: внутри не статического метода" );
}
}
class Main {
public static void main ( String[] args ) {
SuperClass superClassWithSuperCons = new SuperClass();
SuperClass superClassWithSubCons = new SubClass();
SubClass subClassWithSubCons = new SubClass();
superClassWithSuperCons.staticMethod();
superClassWithSubCons.staticMethod();
subClassWithSubCons.staticMethod();
System. out .println();
superClassWithSuperCons.notStaticMethod();
superClassWithSubCons.notStaticMethod();
subClassWithSubCons.notStaticMethod();
}
}
Полученный результат подтверждает написанное выше.
Статические методы интерфейса являются частью интерфейса, и мы не можем их использовать для реализации объектов класса Статические методы в интерфейсах могут быть применены для утилитных методов с целью реализации каких-то проверок, например, проверки на null, сортировки и т.д.
В Java 1.5 появилась реализация импорта статических переменных и статических методов класса, что позволяет обращаться к статическим членам класса непосредственно по имени члена, без дополнительного указания имени класса и пакета. Основная цель статического импорта — улучшение читабельности кода программы благодаря устранению постоянного повторения имени класса.
Реализуется статический импорт на основе декларации static import, с последующим указанием импортируемого класса. Например так:
import static java.util.Arrays.asList;
Обратите внимание, что ключевые слова import и static в данном контексте не относятся к модификаторам доступа, поэтому, правило, что «модификаторы доступа могут следовать в любом порядке» здесь не работает.
5.1 Причины использовать статический импорт
Типовыми примерами использования статического импорта могут быть:
1. Тестирование кода (например, на основе библиотеки AssertJ)
// Без статического импорта
Assertions.assertThat( 1 ).isEqualTo( 2 );
// С использованием статического импорта
import static org.assertj.core.api.Assertions.*;
assertThat( 1 ).isEqualTo( 2 );
2. Использование методов утилитных классов
List numbers = Arrays.asList( 1 , 2 , 3 );
// Имя метода "asList" информативно само по себе
List numbers = asList( 1 , 2 , 3 );
// получение даты следующей пятницы относительно сегодня
LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
// Более элегантное и легкое для чтения выражение
LocalDate.now().with(next(FRIDAY));
Так гладко бывает не всегда, в некоторых случаях статический импорт может ухудшить читабельность кода. Рассмотрим пример без статического импорта:
public class Main {
public static void main (String[] args) {
System.out.println(Math.sqrt(Math.abs(Integer.MIN_VALUE) -
Math.max(Integer.MAX_VALUE, Integer.MIN_VALUE)));
}
}
А теперь тот же самый код, но с импортом:
import static java.lang.Integer.*;
import static java.lang.Math.*;
import static java.lang.Math.max;
public class Main {
public static void main (String[] args) {
System.out.println(sqrt(abs(MIN_VALUE) - max(MAX_VALUE, MIN_VALUE)));
}
}
На первый взгляд код стал более читабелен и короче… Но при этом он демонстрирует основные недостатки использования статического импорта:
1. Код стал хуже читаем, поскольку мы «потеряли» информацию о том, в каком классе переменная или метод определены: MAX_VALUE и MIN_VALUE находятся в классе Integer, Long или они определены в написанном самим программистом классе. Таким образом, указание класса ( Integer.MAX_VALUE ), в данном случае, улучшает читабельность кода 2. Тоже справедливо и для метода max(int a, int b), который определен и в java.lang.Integer и в java.lang.Math . При этом он может быть и самописным методом
Таким образом, каким бы удобным ни был статический импорт, очень важно не злоупотреблять им. Если статический член используется в программе только один или два раза, то его лучше не импортировать. Статический импорт следует оставить на тот случай, если статические члены применяются многократно, как, например, при выполнении целого ряда математических вычислений (но с учетом замечаний, озвученных выше).
Декларация статического импорта пишется в коде как « import static », а не « static import » Если вы импортируете две статических переменных с тем же самым именем, например Integer.MAX_VALUE и Long.MAX_VALUE , то следствием этого вы получите синтаксическую ошибку (их также называют ошибками времени компиляции — Compile-time error ) Статический импорт не всегда улучшает читабельность кода как ожидается. Многие программисты предпочитают использовать Integer.MAX_VALUE , что выглядит понятнее, чем MAX_VALUE Вы можете применять статический импорт не только к статическим переменным (или константам), но также к статическим методам
Статический блок используется для инициализации статических переменных. Хотя статические переменные могут быть инициализированы непосредственно во время объявления, бывают ситуации, когда нам требуется выполнить многострочную обработку.
В таких случаях пригодятся статические блоки
java - Для чего пишут модификаторы private static для переменных?
java - private static и private final static - зачем? - Stack Overflow...
Зачем использовать private static в методах PHP? — Хабр Q&A
Руководство по модификатору static в Java
Курс Java Syntax Pro - Лекция: Статические переменные
Есть ли смысл в private static методах? — Development — Форум
Java private static method | Java Tutorial - YouTube
C# и .NET | Статические члены и модификатор static
Чем по сути отличаются между собой Static , Public и Private - C#...
#16 Ключевые слова static и final | Java для начинающих
private static int totalFuelConsumption — статическая переменная...
#21 - Модификаторы static и final | itProger - Сообщество программистов
Ключевое слово static в PHP | NOP::Nuances of programming
Описание особенностей использования ключевого слова static на языке C#.
Java константы: объявление, примеры static и final
Sex Site
Trainer Porn
Aika Bukkake
Private Static

























































