Ce face static
Un câmp obișnuit există în fiecare obiect. Un câmp static există o singură dată pentru toată clasa și este împărțit de toate obiectele. Îl accesezi prin numele clasei: Contor.total. Este potrivit pentru contoare, cache-uri și constante (static final).
O metodă static se apelează fără obiect: Math.max(3, 7), Integer.parseInt("42"). Pentru că nu are obiect, nu are this și nu poate folosi direct câmpurile sau metodele nestatice. De aceea main este static: JVM-ul îl poate apela fără să construiască un obiect.
Un bloc static { ... } rulează o singură dată, când clasa este încărcată, înainte de prima ei folosire. O clasă internă static nu are legătură cu un obiect al clasei exterioare. Importul static (import static java.lang.Math.*;) permite apelul fără numele clasei.
Exemple
Exemplul 1: Câmp static comun și câmp de obiect
Fiecare bon primește un număr diferit (câmpul obiectului), luat din contorul comun urmatorulNumar (câmpul static).
class Bon {
static int urmatorulNumar = 1;
static double totalZi = 0;
final int numar;
final double suma;
Bon(double suma) {
this.numar = urmatorulNumar++;
this.suma = suma;
totalZi += suma;
}
}
public class Main {
public static void main(String[] args) {
Bon b1 = new Bon(45.50);
Bon b2 = new Bon(12.00);
Bon b3 = new Bon(130.25);
System.out.println("bonuri: " + b1.numar + ", " + b2.numar + ", " + b3.numar);
System.out.println("următorul număr: " + Bon.urmatorulNumar);
System.out.println("total zi: " + Bon.totalZi + " lei");
}
}
Rezultat
bonuri: 1, 2, 3
următorul număr: 4
total zi: 187.75 lei
Exemplul 2: Metode static ajutătoare și blocul static
Clasa Conversii are doar metode statice și un constructor privat, ca nimeni să nu creeze obiecte. Blocul static rulează o singură dată, la prima folosire a clasei.
import java.util.HashMap;
import java.util.Map;
final class Conversii {
private static final Map<String, Double> CURSURI = new HashMap<>();
static {
System.out.println("(se încarcă cursurile)");
CURSURI.put("EUR", 5.08);
CURSURI.put("USD", 4.37);
}
private Conversii() {
}
static double inLei(double suma, String moneda) {
return suma * CURSURI.getOrDefault(moneda, 1.0);
}
static double celsiusInFahrenheit(double c) {
return c * 9 / 5 + 32;
}
}
public class Main {
public static void main(String[] args) {
System.out.println("pornire");
System.out.printf("100 EUR = %.2f lei%n", Conversii.inLei(100, "EUR"));
System.out.printf("20 USD = %.2f lei%n", Conversii.inLei(20, "USD"));
System.out.println("25 °C = " + Conversii.celsiusInFahrenheit(25) + " °F");
}
}
Rezultat
pornire
(se încarcă cursurile)
100 EUR = 508.00 lei
20 USD = 87.40 lei
25 °C = 77.0 °F
Exemplul 3: Din main nu vezi direct câmpurile nestatice
main este static, deci poate apela direct doar alți membri statici. Pentru metoda nestatică saluta trebuie un obiect.
public class Main {
static int vizite = 0;
String limba = "ro";
static void inregistreaza() {
vizite++;
}
String saluta(String nume) {
return limba.equals("ro") ? "Bună, " + nume + "!" : "Hello, " + nume + "!";
}
public static void main(String[] args) {
inregistreaza();
inregistreaza();
System.out.println("vizite: " + vizite);
// System.out.println(saluta("Ana")); // eroare: non-static method cannot be referenced from a static context
Main aplicatie = new Main();
System.out.println(aplicatie.saluta("Ana"));
}
}
Rezultat
vizite: 2
Bună, Ana!
Greșeli frecvente
- Apelezi o metodă nestatică din
main:non-static method saluta(String) cannot be referenced from a static context. Creează un obiect sau fă metodastatic, dacă nu folosește câmpurile obiectului. - Faci un câmp
staticdin greșeală: toate obiectele ajung să împartă aceeași valoare (de exemplu toți elevii au același nume). - Accesezi membrii statici printr-un obiect (
b1.totalZi). Compilează, dar induce în eroare și-Xlintavertizează (static variable should be qualified by type name). ScrieBon.totalZi.
Comenzi înrudite
final (și static final): final interzice schimbarea: o variabilă primește valoare o singură dată, o metodă nu poate fi rescrisă, o clasă nu poate fi extinsă.main și structura unui program: Orice program Java pornește din metoda main a unei clase: public static void main(String[] args).Metode: O metodă grupează cod sub un nume, primește parametri și poate returna o valoare; Java permite supraîncărcare și varargs.Clase interne și anonime: O clasă poate fi declarată în altă clasă (statică sau interioară), într-o metodă (locală) sau direct la folosire, fără nume (anonimă).Pachete și importuri (package, import): package așază clasa într-un pachet (un spațiu de nume, ca un director); import permite folosirea claselor din alte pachete după numele scurt.