Frage

Soweit ich das verstanden die "statische Initialisierung block" wird verwendet, um Werte für statische Feld, wenn es nicht getan werden kann in einer Zeile.

Aber ich verstehe nicht, warum müssen wir einen speziellen block für, dass.Zum Beispiel erklären wir, ein Feld als statisch (ohne Wertzuweisung).Und dann schreiben Sie mehrere Codezeilen zu erstellen, und weisen Sie einen Wert für die oben deklarierte statische Feld.

Warum benötigen wir diese Zeilen in einem speziellen block wie: static {...}?

War es hilfreich?

Lösung

Die nicht-statischen Block:

{
    // Do Something...
}

aufgerufen wird jedes Mal eine Instanz der Klasse aufgebaut ist. Die statischer Block wird nur dem Namen einmal , wenn die Klasse selbst initialisiert wird, unabhängig davon, wie viele Objekte dieses Typs Sie erstellen.

Beispiel:

public class Test {

    static{
        System.out.println("Static");
    }

    {
        System.out.println("Non-static block");
    }

    public static void main(String[] args) {
        Test t = new Test();
        Test t2 = new Test();
    }
}

Dieser Befehl gibt:

Static
Non-static block
Non-static block

Andere Tipps

Wenn sie nicht in einem statischen Initialisierungsbaustein sind, wo würden sie sein? Wie würden Sie eine Variable deklarieren, die nur gemeint war für die Zwecke der Initialisierung lokal sein, und es von einem Feld unterscheiden? Zum Beispiel, wie würde Sie will schreiben:

public class Foo {
    private static final int widgets;

    static {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        widgets = first + second;
    }
}

Wenn first und second nicht in einem Block waren, würden sie wie Felder aus. Wenn sie in einem Block ohne static vor ihm waren, das wäre als Instanz Initialisierungsbaustein zählen anstelle einer statischen Initialisierungsbaustein, so wäre es einmal ausgeführt werden pro aufgebaut Instanz eher einmal als insgesamt.

Jetzt in diesem speziellen Fall eine statische Methode verwenden, könnte stattdessen:

public class Foo {
    private static final int widgets = getWidgets();

    static int getWidgets() {
        int first = Widgets.getFirstCount();
        int second = Widgets.getSecondCount();
        // Imagine more complex logic here which really used first/second
        return first + second;
    }
}

... aber das funktioniert nicht, wenn es mehr Variablen, die Sie wollen aus dem gleichen Block zuzuordnen, oder keinem (zum Beispiel, wenn Sie wollen einfach nur etwas anmelden - oder vielleicht eine native Bibliothek initialisieren).

Hier ist ein Beispiel:

  private static final HashMap<String, String> MAP = new HashMap<String, String>();
  static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

Der Code in dem „statischen“ Abschnitt (en) wird bei Klassenladezeit ausgeführt werden, bevor alle Instanzen der Klasse aufgebaut sind (und bevor irgendwelche statischen Methoden werden von anderer Stelle genannt). Auf diese Weise können Sie sicherstellen, dass die Klasse alle Ressourcen bereit sind, zu verwenden.

Es ist auch möglich, nicht-statische Initialisierer Blöcke zu haben. Diejenigen, wirken wie Erweiterungen der Satz von Konstruktormethoden für die Klasse definiert. Sie sehen aus wie statische Initialisierer Blöcke, außer dem Schlüsselwort „static“ aufgehört hat.

Es ist auch nützlich, wenn Sie tatsächlich wollen nicht den Wert auf etwas, wie das Laden etwas Klasse nur einmal zur Laufzeit zugeordnet werden.

z.

static {
    try {
        Class.forName("com.example.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        throw new ExceptionInInitializerError("Cannot load JDBC driver.", e);
    }
}

Hey, es gibt einen anderen Vorteil, können Sie es verwenden, um Ausnahmen zu behandeln. Stellen Sie sich vor, dass getStuff() hier wirft einen Exception die wirklich gehört in einem catch-Block:

private static Object stuff = getStuff(); // Won't compile: unhandled exception.

dann ein static initializer ist hier nützlich. Sie können dort die Ausnahme behandeln.

Ein weiteres Beispiel ist Sachen zu tun, danach die nicht während der Zuordnung erfolgen:

private static Properties config = new Properties();

static {
    try { 
        config.load(Thread.currentThread().getClassLoader().getResourceAsStream("config.properties");
    } catch (IOException e) {
        throw new ExceptionInInitializerError("Cannot load properties file.", e);
    }
}

Um wieder auf den JDBC-Treiber Beispiel zu kommen, jeder anständige JDBC-Treiber selbst macht auch in der static Verwendung des DriverManager initializer sich zu registrieren. Siehe auch diese und diese Antwort.

Ich würde sagen, static block ist nur syntaktischer Zucker. Es gibt nichts, was man mit static Block tun konnte und nicht mit irgendetwas anderes.

Um einige Beispiele hier gepostet wieder zu verwenden.

Dieses Stück Code neu geschrieben, ohne static initialiser werden.

Methode 1: Mit static

private static final HashMap<String, String> MAP;
static {
    MAP.put("banana", "honey");
    MAP.put("peanut butter", "jelly");
    MAP.put("rice", "beans");
  }

Methode # 2: ohne static

private static final HashMap<String, String> MAP = getMap();
private static HashMap<String, String> getMap()
{
    HashMap<String, String> ret = new HashMap<>();
    ret.put("banana", "honey");
    ret.put("peanut butter", "jelly");
    ret.put("rice", "beans");
    return ret;
}

Es gibt ein paar tatsächlichen Gründe dafür, dass es erforderlich ist, zu existieren:

  1. Initialisierung static final Mitglieder, deren Initialisierung könnte eine Ausnahme auslösen
  2. static final Mitglieder mit den berechneten Werten initialisiert

Die Menschen neigen dazu static {} Blöcke als eine bequeme Art und Weise zu verwenden, um Dinge zu initialisieren, die die Klasse als auch innerhalb der Laufzeit ist abhängig von - wie diese bestimmten Klasse zu gewährleisten geladen wird (zum Beispiel JDBC-Treiber). Das kann auch auf andere Weise erfolgen; jedoch sind die beiden Dinge, die ich oben erwähnt kann nur mit einem Konstrukt wie der static {} Block durchgeführt werden.

Sie können Bit-Code ausführen, wenn für eine Klasse, bevor ein Objekt in den statischen Blöcken aufgebaut ist.

z.

class A {
  static int var1 = 6;
  static int var2 = 9;
  static int var3;
  static long var4;

  static Date date1;
  static Date date2;

  static {
    date1 = new Date();

    for(int cnt = 0; cnt < var2; cnt++){
      var3 += var1;
    }

    System.out.println("End first static init: " + new Date());
  }
}

Es ist ein verbreiteter Irrtum zu denken, dass ein static-block hat nur Zugriff auf statische Felder.Für diese würde ich gerne zeigen, unten Stück code, den ich ziemlich Häufig in real-life-Projekte (kopiert teilweise aus eine andere Antwort in einem etwas anderen Kontext):

public enum Language { 
  ENGLISH("eng", "en", "en_GB", "en_US"),   
  GERMAN("de", "ge"),   
  CROATIAN("hr", "cro"),   
  RUSSIAN("ru"),
  BELGIAN("be",";-)");

  static final private Map<String,Language> ALIAS_MAP = new HashMap<String,Language>(); 
  static { 
    for (Language l:Language.values()) { 
      // ignoring the case by normalizing to uppercase
      ALIAS_MAP.put(l.name().toUpperCase(),l); 
      for (String alias:l.aliases) ALIAS_MAP.put(alias.toUpperCase(),l); 
    } 
  } 

  static public boolean has(String value) { 
    // ignoring the case by normalizing to uppercase
    return ALIAS_MAP.containsKey(value.toUpper()); 
  } 

  static public Language fromString(String value) { 
    if (value == null) throw new NullPointerException("alias null"); 
    Language l = ALIAS_MAP.get(value); 
    if (l == null) throw new IllegalArgumentException("Not an alias: "+value); 
    return l; 
  } 

  private List<String> aliases; 
  private Language(String... aliases) { 
    this.aliases = Arrays.asList(aliases); 
  } 
} 

Hier die Initialisierung wird verwendet, um einen index (ALIAS_MAP), zum anzeigen einer Reihe von Aliasnamen zurück, um die original-enum-Typ.Es ist gedacht als eine Erweiterung zu die gebaut-in valueOf-Methode zur Verfügung gestellt durch die Enum selbst.

Wie Sie sehen können, wird der statische Initialisierer greift auf selbst die private Feld aliases.Es ist wichtig zu verstehen, dass die static block bereits Zugriff auf die Enum Wert Instanzen (z.B. ENGLISH).Dies ist, weil die Reihenfolge der Initialisierung und Ausführung bei Enum Typen, gerade so , als ob die static private Felder initialisiert wurden mit den Instanzen vor dem static Blöcke wurden genannt:

  1. Die Enum Konstanten, die implizite statische Felder.Dies erfordert die Enum-Konstruktor Beispiel Blöcke, und Instanz-Initialisierung auftreten, zunächst als gut.
  2. static block und Initialisierung von statischen Feldern in der Reihenfolge des Auftretens.

Diese out-of-order-Initialisierung (Konstruktor vor static block) ist zu beachten.Es passiert auch, wenn wir Initialisierung statischer Felder mit den Instanzen ähnlich zu einem Singleton (Vereinfachungen):

public class Foo {
  static { System.out.println("Static Block 1"); }
  public static final Foo FOO = new Foo();
  static { System.out.println("Static Block 2"); }
  public Foo() { System.out.println("Constructor"); }
  static public void main(String p[]) {
    System.out.println("In Main");
    new Foo();
  }
}

Was wir sehen, ist die folgende Ausgabe:

Static Block 1
Constructor
Static Block 2
In Main
Constructor

Klar ist, dass die statische Initialisierung tatsächlich passieren kann bevor der Konstruktor, und auch nach:

Einfach Zugriff auf Foo in der main-Methode bewirkt, dass die Klasse, die geladen werden und die statische Initialisierung zu starten.Aber als Teil der Statischen Initialisierung rufen wir wieder die Konstruktoren für statische Felder, nach denen es fortgesetzt wird die statische Initialisierung und Abschluss der Konstruktor aufgerufen innerhalb der main-Methode.Eher komplexe situation, für die ich hoffe, dass in der normalen Kodierung wären wir nicht haben zu deal mit.

Für weitere Informationen hierzu siehe das Buch "Effektive Java".

Wenn Sie Ihre statischen Variablen müssen zur Laufzeit festgelegt werden dann ein static {...} Block ist sehr hilfreich.

Zum Beispiel, wenn Sie das statische Element auf einen Wert setzen, die in einer Konfigurationsdatei oder Datenbank gespeichert ist.

Auch nützlich, wenn Sie wollen Werte zu einem statischen Map Mitglied hinzufügen, wie Sie diese Werte nicht in der Anfangselementdeklaration hinzufügen können.

So können Sie ein statisches Feld (es auch „Klassenvariable“ genannt wird, weil er gehört die Klasse und nicht auf eine Instanz der Klasse, mit anderen Worten ist es mit der Klasse verbunden, anstatt mit einem Objekt), und Sie wollen initialisieren. Also, wenn Sie wollen nicht eine Instanz dieser Klasse erstellen, und Sie möchten dieses statische Feld manipulieren, können Sie es auf drei Arten tun:

1- Einfach initialisieren, wenn Sie die Variable deklarieren:

static int x = 3;

2- Haben Sie einen statischen Initialisierungsblock:

static int x;

static {
 x=3;
}

3- Haben Sie eine Klassenmethode (statische Methode), die die Klasse Variable zugreift und initialisiert sie: Dies ist die Alternative zu dem obigen statischen Block; Sie können eine private statische Methode schreiben:

public static int x=initializeX();

private static int initializeX(){
 return 3;
}

Nun, warum würden Sie verwenden statische Initialisierungsblock anstelle von statischen Methoden?

Es ist wirklich zu dem, was Sie in Ihrem Programm benötigen. Aber müssen Sie diese statische Initialisierungsblock wissen einmal aufgerufen wird und der einzige Vorteil der Klassenmethode ist, dass sie später wiederverwendet werden können, wenn Sie die Klassenvariable neu zu initialisieren müssen.

Lassen Sie sich sagt, dass Sie einen komplexen Array in Ihrem Programm haben. Sie initialisieren (mit für Schleife zum Beispiel) und dann die Werte in diesem Array werden im gesamten Programm ändern, aber dann irgendwann wollen Sie es neu zu initialisieren (geht zurück auf den Ausgangswert). In diesem Fall können Sie die private static Methode aufrufen. Für den Fall, Sie müssen nicht in Ihrem Programm die Werte neu zu initialisieren, kann man einfach den statischen Block verwenden und keine Notwendigkeit für eine statische Methode, da Sie nicht gonna verwenden sind es später im Programm.

Hinweis: die statischen Blöcke werden in der Reihenfolge, wie sie im Code erscheinen genannt.

Beispiel 1:

class A{
 public static int a =f();

// this is a static method
 private static int f(){
  return 3;
 }

// this is a static block
 static {
  a=5;
 }

 public static void main(String args[]) {
// As I mentioned, you do not need to create an instance of the class to use the class variable
  System.out.print(A.a); // this will print 5
 }

}

Beispiel 2:

class A{
 static {
  a=5;
 }
 public static int a =f();

 private static int f(){
  return 3;
 }

 public static void main(String args[]) {
  System.out.print(A.a); // this will print 3
 }

}

Als Zusatz, wie @Pointy sagte

  

Der Code in dem „statischen“ Abschnitt (en) wird bei Klasse Last ausgeführt werden   Zeit, bevor alle Instanzen der Klasse sind so konstruiert (und vor   alle statischen Methoden werden von anderer Stelle genannt).

Es soll System.loadLibrary("I_am_native_library") in statischen Block hinzuzufügen.

static{
    System.loadLibrary("I_am_a_library");
}

Es wird garantiert keine native Methode vor der Bibliothek in den Speicher geladen wird verwandten aufgerufen werden.

Nach

Sie müssen zuerst verstehen, dass Ihre Anwendung Klassen selbst instanziiert Objekte während der Laufzeit java.class.Class. Dies ist, wenn Sie Ihre statischen Blöcke liefen werden. So kann man tatsächlich tun:

public class Main {

    private static int myInt;

    static {
        myInt = 1;
        System.out.println("myInt is 1");
    }

    //  needed only to run this class
    public static void main(String[] args) {
    }

}

und es würde drucken „myInt 1“ zu trösten. Beachten Sie, dass ich habe keine Klasse instanziiert.

static int B,H;
static boolean flag = true;
static{
    Scanner scan = new Scanner(System.in);
    B = scan.nextInt();
    scan.nextLine();
    H = scan.nextInt();

    if(B < 0 || H < 0){
        flag = false;
        System.out.println("java.lang.Exception: Breadth and height must be positive");
    } 
}

statischer Block wird für jede Technologie verwendet, um statisches Datenelement in dynamischer Art und Weise zu initialisieren, oder wir können für die dynamische Initialisierung von statischen Daten Mitglied statischen Block sagen wird used..Because sind für nicht statische Daten Memberinitialisierungsliste wir Konstruktor haben, aber wir keine Stelle haben, wo wir dynamisch statisches Datenelement initialisieren

Eg:-class Solution{
         // static int x=10;
           static int x;
       static{
        try{
          x=System.out.println();
          }
         catch(Exception e){}
        }
       }

     class Solution1{
      public static void main(String a[]){
      System.out.println(Solution.x);
        }
        }

Nun mein static int x wird initialisieren ..Bcoz dynamisch, wenn Compiler Solution.x gehen wird es Abhilfe Klasse und statische Blocklast bei Laden von Klassen laden wird time..So wir in der Lage, dynamisch, dass statisches Datenelement zu initialisieren, um ..

}

scroll top