Jaka jest różnica między inicjalizacją w static
bloku:
public class staticTest {
static String s;
static int n;
static double d;
static {
s = "I'm static";
n = 500;
d = 4000.0001;
}
...
I indywidualna inicjalizacja statyczna:
public class staticTest {
static String s = "I'm static";
static int n = 500;
static double d = 4000.0001;
....
java
static-initialization
Adam Matan
źródło
źródło
Odpowiedzi:
Statyczne bloki inicjalizacyjne umożliwiają bardziej złożoną inicjalizację, na przykład przy użyciu warunków:
static double a; static { if (SomeCondition) { a = 0; } else { a = 1; } }
Lub gdy wymagane jest coś więcej niż tylko konstrukcja: podczas korzystania z konstruktora do tworzenia instancji konieczna jest obsługa wyjątków lub praca inna niż tworzenie pól statycznych.
Blok inicjalizacji statycznej jest również uruchamiany po wbudowanych statycznych inicjalizatorach, więc prawidłowe są następujące zasady:
static double a; static double b = 1; static { a = b * 4; // Evaluates to 4 }
źródło
Typowe zastosowanie:
private final static Set<String> SET = new HashSet<String>(); static { SET.add("value1"); SET.add("value2"); SET.add("value3"); }
Jak byś to zrobił bez statycznego inicjatora?
źródło
SET
i użyj zmiennej initializer (private final static Set<String> SET = createValueSet()
). A co, jeśli masz 5 zestawów i 2 mapy, czy po prostu wrzucisz je wszystkie do jednegostatic
bloku?Możesz użyć bloku try / catch wewnątrz,
static{}
jak poniżej:MyCode{ static Scanner input = new Scanner(System.in); static boolean flag = true; static int B = input.nextInt(); static int H = input.nextInt(); static{ try{ if(B <= 0 || H <= 0){ flag = false; throw new Exception("Breadth and height must be positive"); } }catch(Exception e){ System.out.println(e); } } }
PS: W odniesieniu do tego !
źródło
Innym powodem jest obsługa wyjątków podczas inicjalizacji. Na przykład:
static URL url; static { try { url = new URL("https://blahblah.com"); } catch (MalformedURLException mue) { //log exception or handle otherwise } }
Jest to przydatne dla konstruktorów, które irytująco zgłaszają sprawdzone wyjątki, jak powyżej, lub bardziej złożoną logikę inicjalizacji, która może być podatna na wyjątki.
źródło
Czasami chcesz zrobić coś więcej niż tylko przypisać wartości do zmiennych statycznych. Ponieważ nie można umieszczać dowolnych instrukcji w treści klasy, można użyć statycznego bloku inicjatora.
źródło
W twoim przykładzie nie ma różnicy; ale często wartość początkowa jest bardziej złożona, niż jest to wygodnie wyrażone w pojedynczym wyrażeniu (np. jest to a,
List<String>
którego zawartość najlepiej wyrazić za pomocąfor
-loop; lub toMethod
może nie istnieć, więc potrzebne są procedury obsługi wyjątków) i / lub pola statyczne należy ustawić w określonej kolejności.źródło
static
block może służyć do inicjowania pojedynczego wystąpienia, aby zapobiec używaniu metody synchronizowanejgetInstance()
.źródło
Technicznie rzecz biorąc, można by się bez niego obejść. Niektórzy wolą wielowierszowy kod inicjujący, aby przejść do metody statycznej. Jestem całkiem zadowolony używając statycznego inicjalizatora do stosunkowo prostej inicjalizacji wielostanowiskowej.
Oczywiście prawie zawsze robiłem swoje statystyki
final
i wskazywałem na niemodyfikowalny obiekt.źródło
Statyczne słowo kluczowe (niezależnie od tego, czy jest to zmienna, czy blok) należy do klasy. Więc kiedy klasa jest wywoływana, te zmienne lub bloki są wykonywane. Więc większość inicjalizacji zostanie wykonana za pomocą słowa kluczowego static. Ponieważ należy do samej klasy, klasa może uzyskać do niej bezpośredni dostęp, bez tworzenia instancji klasy.
Przykład:
class Shoe { int size; String colour; static String brand = "Nike"; public Shoe(int size, String colour) { super(); this.size = size; this.colour = colour; } void displayShoe() { System.out.printf("%-2d %-8s %s %n",size,colour, brand); } public static void main(String args[]) { Shoe s1 = new Shoe(7, "Blue"); Shoe s2 = new Shoe(8, "White"); System.out.println("================="); s1.displayShoe(); s2.displayShoe(); System.out.println("================="); } }
źródło
Używamy konstruktorów do inicjalizacji naszych zmiennych instancji (zmienne niestatyczne, zmienne należące do obiektów, a nie do klasy).
Jeśli chcesz zainicjować zmienne klasowe (zmienne statyczne) i chcesz to zrobić bez tworzenia obiektu (konstruktory można wywołać tylko podczas tworzenia obiektu), potrzebujesz bloków statycznych.
static Scanner input = new Scanner(System.in); static int widht; static int height; static { widht = input.nextInt(); input.nextLine(); height = input.nextInt(); input.close(); if ((widht < 0) || (height < 0)) { System.out.println("java.lang.Exception: Width and height must be positive"); } else { System.out.println("widht * height = " + widht * height); } }
źródło
System.out.println("B * H");
jest całkiem bezużyteczny. A sama odpowiedź jest dość niejasna. OP nie wspomniał o konstruktorach ani zmiennych instancji.Statyczny blok kodu umożliwia inicjalizację pól z więcej niż instucją, inicjalizację pól w innej kolejności deklaracji, a także może być używany do warunkowej inicjalizacji.
Dokładniej,
static final String ab = a+b; static final String a = "Hello,"; static final String b = ", world";
nie zadziała, ponieważ a i b są zadeklarowane po ab.
Jednak mogłem użyć statycznego init. blok, aby to przezwyciężyć.
static final String ab; static final String a; static final String b; static { b = ", world"; a = "Hello"; ab = a + b; } static final String ab; static final String a; static final String b; static { b = (...) ? ", world" : ", universe"; a = "Hello"; ab = a + b; }
źródło
ab
deklarację poniżej deklaracjib
.Blok inicjalizacji statycznej jest przydatny, jeśli chcesz zainicjować określone typy statyczne klas, przed pierwszym użyciem klasy. Późniejsze użycie nie spowoduje wywołania żadnych statycznych bloków inicjalizacyjnych. Jest to przeciwieństwo inicjatorów instancji, które inicjują elementy członkowskie instancji.
źródło
Jeśli chcesz ocenić dane wyrażenie podczas ładowania klasy, możesz skorzystać z bloku statycznego, ale pamiętaj:
źródło