Un ghid pentru cuvântul cheie static în Java

1. Introducere

În acest articol, vom explora în detaliu cuvântul cheie static al limbajului Java. Vom afla cum putem aplica cuvinte cheie statice variabilelor, metodelor, blocurilor, claselor imbricate și ce diferență are.

2. Anatomia cuvântului cheie static

În limbajul de programare Java, cuvântul cheie static indică faptul că membrul respectiv aparține unui tip în sine, mai degrabă decât unei instanțe de acel tip .

Aceasta înseamnă că este creată o singură instanță din acel membru static, care este partajată între toate instanțele clasei.

Cuvântul cheie poate fi aplicat variabilelor, metodelor, blocurilor și clasei imbricate.

3. Câmpurile statice (sau variabile de clasă)

În Java, dacă un câmp este declarat static , atunci exact o singură copie a câmpului respectiv este creată și partajată între toate instanțele clasei respective . Nu contează de câte ori inițializăm o clasă; va exista întotdeauna o singură copie a câmpului static care îi aparține. Valoarea acestui câmp static va fi împărtășită între toate obiectele oricăruia dintre aceleași, din orice clasă diferită.

Din perspectiva memoriei, variabilele statice intră într-un anumit pool din memoria JVM numită Metaspace (înainte de Java 8, acest pool se numea Permanent Generation sau PermGen, care a fost complet eliminat și înlocuit cu Metaspace).

3.1. Exemplu de câmp static

Să presupunem că avem o clasă Car cu mai multe atribute (variabile de instanță) . Ori de câte ori obiecte noi sunt inițializate din acest plan de mașină , fiecare obiect nou va avea o copie distinctă a acestor variabile de instanță.

Totuși, să presupunem că căutăm o variabilă care să țină contul numărului de obiecte auto care sunt inițializate și care este partajat între toate instanțele, astfel încât să poată accesa și să o incrementeze la inițializarea lor.

Aici intervin variabilele statice :

public class Car { private String name; private String engine; public static int numberOfCars; public Car(String name, String engine) { this.name = name; this.engine = engine; numberOfCars++; } // getters and setters }

Acum, pentru fiecare obiect din această clasă care este inițializat, se incrementează aceeași copie a variabilei numberOfCars . Deci, pentru acest caz, următoarele afirmații vor fi adevărate:

@Test public void whenNumberOfCarObjectsInitialized_thenStaticCounterIncreases() { new Car("Jaguar", "V8"); new Car("Bugatti", "W16"); assertEquals(2, Car.numberOfCars); }

3.2. Motive convingătoare pentru a utiliza câmpuri statice

  • Când valoarea variabilei este independentă de obiecte
  • Când se presupune că valoarea este partajată între toate obiectele

3.3. Puncte cheie de reținut

  • Deoarece variabilele statice aparțin unei clase, ele pot fi accesate direct folosind numele clasei și nu au nevoie de nicio referință de obiect
  • variabilele statice pot fi declarate doar la nivel de clasă
  • câmpurile statice pot fi accesate fără inițializarea obiectului
  • Deși putem accesa câmpuri statice folosind o referință de obiect (cum ar fi ford.numberOfCars ++ ), ar trebui să ne abținem de la utilizarea acestuia, deoarece în acest caz devine dificil să ne dăm seama dacă este o variabilă de instanță sau o variabilă de clasă; în schimb, ar trebui să ne referim întotdeauna la variabilele statice folosind numele clasei (de exemplu, în acest caz, Car.numberOfCars ++ )

4. Metodele statice (sau metodele de clasă)

Similar câmpurilor statice , metodele statice aparțin, de asemenea, unei clase în locul obiectului și astfel pot fi apelate fără a crea obiectul clasei în care se află. Sunt menite să fie utilizate fără a crea obiecte ale clasei.

4.1. Exemplu de metodă statică

metodele statice sunt utilizate în general pentru a efectua o operație care nu depinde de crearea instanței.

Dacă există un cod care ar trebui distribuit între toate instanțele clasei respective, atunci scrieți codul respectiv într-o metodă statică :

public static void setNumberOfCars(int numberOfCars) { Car.numberOfCars = numberOfCars; }

metodele statice sunt, de asemenea, utilizate pe scară largă pentru a crea clase de utilitate sau de ajutor, astfel încât să poată fi obținute fără a crea un nou obiect al acestor clase.

Aruncați o privire asupra claselor de utilități Collections sau Math din JDK, StringUtils din Apache sau CollectionUtils din Spring cadru și observați că toate metodele sunt statice .

4.2. Motive convingătoare pentru utilizarea metodelor statice

  • Pentru a accesa / manipula variabile statice și alte metode statice care nu depind de obiecte
  • metodele statice sunt utilizate pe scară largă în clasele de utilități și ajutoare

4.3. Puncte cheie de reținut

  • metodele statice din Java sunt rezolvate la compilare. Deoarece suprascrierea metodei face parte din polimorfismul Runtime, deci metodele statice nu pot fi anulate
  • metodele abstracte nu pot fi statice
  • metodele statice nu pot utiliza acest cuvânt cheie sau super cuvinte cheie
  • Următoarele combinații de instanță, metode de clasă și variabile sunt valabile:
    1. Metodele de instanță pot accesa direct atât metodele de instanță, cât și variabilele de instanță
    2. Metode de exemplu , pot , de asemenea , acces statice variabile și statice metode direct
    3. metodele statice pot accesa toate variabilele statice și alte metode statice
    4. metodele statice nu pot accesa direct variabilele de instanță și metodele de instanță ; au nevoie de o referință la obiect pentru a face acest lucru

5. Un bloc static

Un bloc static este utilizat pentru inițializarea variabilelor statice . Deși variabilele statice pot fi inițializate direct în timpul declarației, există situații în care suntem obligați să facem procesarea multilinie.

În astfel de cazuri, blocurile statice sunt utile.

Dacă variabilele statice necesită logică suplimentară cu mai multe instrucțiuni în timpul inițializării, atunci poate fi utilizat un bloc static .

5.1. Static Exemplul Block

Să presupunem că vrem să inițializăm un obiect list cu câteva valori predefinite.

Acest lucru devine ușor cu blocurile statice :

public class StaticBlockDemo { public static List ranks = new LinkedList(); static { ranks.add("Lieutenant"); ranks.add("Captain"); ranks.add("Major"); } static { ranks.add("Colonel"); ranks.add("General"); } }

În acest exemplu, nu ar fi posibilă inițializarea obiectului List cu toate valorile inițiale împreună cu declarația; și de aceea am folosit blocul static aici.

5.2. Motive convingătoare pentru utilizarea blocurilor statice

  • Dacă inițializarea variabilelor statice necesită o logică suplimentară, cu excepția atribuirii
  • Dacă inițializarea variabilelor statice este predispusă la erori și necesită gestionarea excepțiilor

5.3. Puncte cheie de reținut

  • O clasă poate avea mai multe blocuri statice
  • câmpurile statice și blocurile statice sunt rezolvate și executate în aceeași ordine în care sunt prezente în clasă

6. O clasă statică

Limbajul de programare Java ne permite să creăm o clasă în cadrul unei clase. Oferă un mod convingător de grupare a elementelor care vor fi folosite doar într-un singur loc, ceea ce ajută la menținerea codului nostru mai organizat și mai ușor de citit.

Arhitectura de clasă imbricată este împărțită în două:

  • clasele imbricate care sunt declarate statice se numesc clase imbricate statice întrucât,
  • nested classes that are non-static are called inner classes

The main difference between these two is that the inner classes have access to all member of the enclosing class (including private), whereas the static nested classes only have access to static members of the outer class.

In fact, static nested classes behaved exactly like any other top-level class but enclosed in the only class which will access it, to provide better packaging convenience.

6.1. Example of static Class

The most widely used approach to create singleton objects is through static nested class is it doesn't require any synchronization and is easy to learn and implement:

public class Singleton { private Singleton() {} private static class SingletonHolder { public static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }

6.2. Compelling Reasons to Use a static Inner Class

  • Grouping classes that will be used only in one place increases encapsulation
  • The code is brought closer to the place that will be only one to use it; this increases readability and code is more maintainable
  • If nested class doesn't require any access to it's enclosing class instance members, then it's better to declare it as static because this way, it won't be coupled to the outer class and hence will be more optimal as they won't require any heap or stack memory

6.3. Key Points to Remember

  • static nested classes do not have access to any instance members of the enclosing outer class; it can only access them through an object's reference
  • clasele statice imbricate pot accesa toți membrii statici ai clasei de închidere, inclusiv cei privați
  • Specificațiile de programare Java nu ne permit să declarăm clasa de nivel superior ca statică ; numai clasele din clasele (clase imbricate) pot fi făcute ca statice

7. Concluzie

În acest articol, am văzut cuvântul cheie static în acțiune. De asemenea, citim despre motivele și avantajele utilizării câmpurilor statice, metodelor statice, blocurilor statice și claselor interioare statice.

Ca întotdeauna, putem găsi codul complet pe GitHub.