JavaRush /Blogue Java /Random-PT /10 notas sobre o modificador estático em Java

10 notas sobre o modificador estático em Java

Publicado no grupo Random-PT
O modificador estático em Java está diretamente associado à classe. Se o campo for estático então pertence à classe, se o método for estático é a mesma coisa: pertence à classe. Com base nisso, você pode acessar um método ou campo estático usando o nome da classe. Por exemplo, se o campo de contagem for estático na classe Counter, você poderá acessar a variável com uma consulta como: Counter.count. 10 notas sobre o modificador estático em Java - 1Antes de começarmos com as notas, vamos lembrar (e talvez descobrir) o que é estático e o que pode ser estático em Java. Estático é um modificador aplicado a um campo, bloco, método ou classe interna. Este modificador indica que o assunto está vinculado à classe atual.

Campos estáticos

Quando denotamos uma variável em nível de classe, indicamos que o valor pertence a uma classe. Se você não fizer isso, o valor da variável será vinculado a um objeto criado usando esta classe. O que isso significa? 10 notas sobre o modificador estático em Java - 2E o fato é que se a variável não for estática, então cada novo objeto desta classe terá seu próprio valor desta variável, alterando o qual a alteramos exclusivamente em um objeto: Por exemplo, temos uma classe Car com um não -variável estática:
public class Car {
  int km;
}
Então no principal:
Car orangeCar = new Car();
orangeCar.km = 100;

Car blueCar = new Car();
blueCar.km = 85;

System.out.println("Orange car - " + orangeCar.km);
System.out.println("Blue car - " + blueCar.km);
A saída que obtemos é:

Orange car - 100
Blue car - 85
Como você pode ver, cada objeto possui sua própria variável, cuja alteração ocorre apenas para este objeto. Bom, se tivermos uma variável estática, então esse valor global é o mesmo para todos: Agora temos um Carro com uma variável estática:
public class Car {
  static int km;
}
Então o mesmo código em main será enviado para o console:

Orange car - 85
Blue car - 85
Afinal, temos uma variável para todos nós e sempre a alteramos. Variáveis ​​estáticas geralmente são acessadas não por uma referência de objeto - orangeCar.km, mas pelo nome da classe - Car.km

Bloco estático

Existem dois blocos de inicialização – regular e estático. O bloco destina-se a inicializar variáveis ​​internas. Se o bloco for normal, as variáveis ​​internas do objeto serão inicializadas com ele, mas se for estático, as variáveis ​​estáticas (ou seja, variáveis ​​de classe) serão atribuídas a eles. Exemplo de classe com bloco de inicialização estático:
public class Car {
  static int km;

  static {
     km = 150;
  }
}

Método estático

Os métodos estáticos diferem dos métodos regulares porque também estão vinculados a uma classe em vez de a um objeto. Uma propriedade importante de um método estático é que ele só pode acessar variáveis/métodos estáticos. Como exemplo, vejamos uma classe que será uma espécie de contador que monitora as chamadas de métodos:
public class Counter {
  static int count;

  public static void invokeCounter() {
     count++;
     System.out.println("Current counter value - " + count);
  }
}
Vamos chamá-lo em main:
Counter.invokeCounter();
Counter.invokeCounter();
Counter.invokeCounter();
E obtemos a saída para o console:

Текущее meaning счётчика - 1
Текущее meaning счётчика - 2
Текущее meaning счётчика - 3

Classe estática em Java

Somente uma classe interna pode ser uma classe estática. Novamente, esta classe está vinculada à classe externa e, se a classe externa for herdada por outra classe, esta não será herdada. Além disso, esta classe pode ser herdada, assim como pode ser herdada de qualquer outra classe e implementar uma interface. Essencialmente, uma classe aninhada estática não é diferente de qualquer outra classe interna, exceto que seu objeto não contém uma referência ao objeto da classe externa que a criou. No entanto, isso torna uma classe estática mais semelhante a uma classe normal não aninhada, porque a única diferença é que ela está agrupada em outra classe. Em alguns casos, isso é uma vantagem para nós, pois a partir dele temos acesso às variáveis ​​estáticas privadas da classe externa. Exemplo de uma classe estática aninhada:
public class Vehicle {

  public static class Car {
     public int km;
  }
}
Criando uma instância desta classe e definindo o valor da variável interna:
Vehicle.Car car = new Vehicle.Car();
car.km = 90;
Para usar métodos/variáveis/classes estáticas, não precisamos criar um objeto dessa classe. É claro que os modificadores de acesso devem ser levados em consideração. Por exemplo, os campos privatesó são acessíveis dentro da classe em que são declarados. Os campos protectedestão disponíveis para todas as classes dentro de um pacote ( package ), bem como para todas as classes herdeiras fora do pacote. Para mais detalhes, confira o artigo “ privado vs protegido vs público ”. Suponha que exista um método estático increment()na classe Countercuja tarefa seja incrementar o contador count. Para chamar esse método, você pode usar uma invocação no formato Counter.increment(). Não há necessidade de instanciar uma classe Counterpara acessar um campo ou método estático. Esta é a diferença fundamental entre objetos estáticos e não estáticos (membros da classe). Deixe-me lembrá-lo mais uma vez que os membros da classe estática pertencem diretamente à classe, não à sua instância. Ou seja, o valor de uma variável estática countserá o mesmo para todos os objetos do tipo Counter. Posteriormente neste artigo, veremos os aspectos fundamentais do uso do modificador estático em Java, bem como alguns recursos que o ajudarão a compreender os principais conceitos de programação.

O que todo programador deve saber sobre o modificador Static em Java

Nesta seção, veremos os fundamentos do uso de métodos, campos e classes estáticos. Vamos começar com as variáveis.
  1. Você NÃO pode acessar membros não estáticos de uma classe dentro de um contexto estático, como um método ou bloco. Compilar o código abaixo resultará em um erro:

    public class Counter{
    private int count;
    public static void main(String args[]){
       System.out.println(count); //compile time error
    }}

    Este é um dos erros mais comuns cometidos por programadores Java, especialmente iniciantes. Como o método mainé estático, mas a variável countnão, neste caso o método printlndentro do método maingerará “Erro de tempo de compilação”.

  2. В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите — «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких How «состояние гонки» (race condition).

  3. Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый an object для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы How нельзя лучше подходят в качестве методов-фабрик (factory), и методов-утorт (utility). Класс java.lang.Math — замечательный пример, в котором почти все методы статичны, по этой же причине классы-утorты в Java финализированы (final).

  4. Другим важным моментом является то, что вы НЕ можете переопределять (Override) статические методы. Если вы объявите такой же метод в классе-наследнике (subclass), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса (superclass) instead of переопределения. Это явление известно How сокрытие методов (hiding methods). Это означает, что при обращении к статическому методу, который объявлен How в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:

    class Vehicle{
         public static void  kmToMiles(int km){
              System.out.println("Inside parent class/static method");
         } }
    
    class Car extends Vehicle{
         public static void  kmToMiles(int km){
              System.out.println("Inside child class/static method ");
         } }
    
    public class Demo{
       public static void main(String args[]){
          Vehicle v = new Car();
           v.kmToMiles(10);
      }}

    Вывод в консоль:

    Внутри родительского класса/статического метода

    Код наглядно демонстрирует: несмотря на то, что an object имеет тип Car, вызван статический метод из класса Vehicle, т.к. произошло обращение к методу во время компиляции. И заметьте, ошибки во время компиляции не возникло!

  5. Объявить статическим также можно и класс, за исключением классов верхнего уровня. Такие классы известны How «вложенные статические классы» (nested static class). Они бывают полезными для представления улучшенных связей. Яркий пример вложенного статического класса — HashMap.Entry, который предоставляет структуру данных внутри HashMap. Стоит заметить, также How и любой другой внутренний класс, вложенные классы находятся в отдельном файле .class. Таким образом, если вы объявor пять вложенных классов в вашем главном классе, у вас будет 6 файлов с расширением .class. Ещё одним примером использования является объявление собственного компаратора (Comparator), например компаратор по возрасту (AgeComparator) в классе сотрудники (Employee).

  6. Модификатор static также может быть объявлен в статичном блоке, более известным How «Статический блок инициализации» (Static initializer block), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.

  7. Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных or не статических методов, которые связываются во время исполнения на реальном an objectе. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности or необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утorты хорошие образцы применения модификатора static. Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java», которая является обязательной для прочтения каждым программистом данного языка.

  8. Важным свойством статического блока является инициализация. Статические поля or переменные инициализируются после загрузки класса в память. Порядок инициализации сверху вниз, в том же порядке, в Howом они описаны в исходном файле Java класса. Поскольку статические поля инициализируются на потокобезопасный манер, это свойство также используется для реализации паттерна Singleton. Если вы не используется список Enum How Singleton, по тем or иным причинам, то для вас есть хорошая альтернатива. Но в таком случае необходимо учесть, что это не «ленивая» инициализация. Это означает, что статическое поле будет проинициализировано ещё ДО того How кто-нибудь об этом «попросит». Если an object ресурсоёмкий or редко используется, то инициализация его в статическом блоке сыграет не в вашу пользу.

  9. Durante a serialização, assim como transientas variáveis, os campos estáticos não são serializados. Na verdade, se você salvar quaisquer dados em um campo estático, após a desserialização o novo objeto conterá seu valor primário (padrão), por exemplo, se o campo estático for uma variável do tipo int, então seu valor após a desserialização será zero, se o tipo floaté 0,0, se tipo Objectnull. Honestamente, esta é uma das perguntas mais frequentes sobre serialização em entrevistas Java. Não armazene os dados mais importantes sobre um objeto em um campo estático!

  10. E finalmente, vamos falar sobre static import. Este modificador tem muito em comum com o operador padrão import, mas ao contrário dele, permite importar um ou todos os membros estáticos de uma classe. Ao importar métodos estáticos, eles podem ser acessados ​​como se estivessem definidos na mesma classe, da mesma forma que ao importar campos, podemos acessá-los sem especificar o nome da classe. Este recurso foi introduzido no Java versão 1.5 e, quando usado corretamente, melhora a legibilidade do código. Esta construção é mais frequentemente encontrada em testes JUnit , porque Quase todos os desenvolvedores de testes usam static importmétodos assert, por exemplo, assertEquals()e suas duplicatas sobrecarregadas. Se nada estiver claro, seja bem-vindo para obter informações adicionais .

Isso é tudo. Todo programador deve conhecer todos os pontos acima sobre o modificador estático em Java . Este artigo abordou informações básicas sobre variáveis ​​estáticas, campos, métodos, blocos de inicialização e importações. Incluindo algumas propriedades importantes, cujo conhecimento é fundamental ao escrever e compreender programas em Java. Espero que cada desenvolvedor aperfeiçoe suas habilidades no uso de conceitos estáticos porque... Isso é muito importante para uma programação séria."
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION