Question

Que j'ai compris le "bloc d'initialisation statique" est utilisé pour définir les valeurs de champ statique si elle ne peut pas être fait en une seule ligne.

Mais je ne comprends pas pourquoi nous avons besoin d'un bloc spécial pour cela.Par exemple, nous déclarons un champ statique (sans affectation de la valeur).Et puis écrire plusieurs lignes de code qui génère et assigner une valeur à la ci-dessus a déclaré champ statique.

Pourquoi avons-nous besoin de ces lignes dans un bloc spécial comme: static {...}?

Était-ce utile?

La solution

bloc non statique:

{
    // Do Something...
}

est appelée chaque fois une instance de la classe est construite. bloc statique n'est appelée une fois , lorsque la classe elle-même est initialisé, peu importe le nombre d'objets de ce type que vous créez.

Exemple:

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();
    }
}

Cette affiche:

Static
Non-static block
Non-static block

Autres conseils

Si elles ne sont pas dans un bloc d'initialisation statique, où seraient-ils? Comment voulez-vous déclarer une variable qui était uniquement destinée à être locale aux fins de l'initialisation et le distinguer d'un terrain? Par exemple, comment voulez écrire:

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;
    }
}

Si first et second ne sont pas dans un bloc, ils regarderait comme les champs. Si elles étaient dans un bloc sans static devant elle, qui compterait comme un bloc d'initialisation de l'instance au lieu d'un bloc d'initialisation statique, il serait exécuté une fois par exemple construit plutôt qu'une fois au total.

Dans ce cas particulier, vous pouvez utiliser une méthode statique à la place:

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;
    }
}

... mais cela ne fonctionne pas quand il y a plusieurs variables que vous souhaitez attribuer dans le même bloc, ou pas (par exemple si vous voulez juste quelque chose connecter - ou peut-être initialiser une bibliothèque native).

Voici un exemple:

  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");
  }

Le code dans la section « statique » (s) sera exécutée au moment du chargement de la classe, avant que les instances de la classe sont construites (et avant toutes les méthodes statiques sont appelées d'ailleurs). De cette façon, vous pouvez vous assurer que les ressources de la classe sont prêtes à l'emploi.

Il est aussi possible d'avoir des blocs de initialiseur non statiques. Ceux-ci agissent comme des extensions à l'ensemble des méthodes de constructeur définies pour la classe. Ils ressemblent à des blocs statiques initialiseur, sauf le mot-clé « statique » reste éteint.

Il est également utile lorsque vous ne voulez pas vraiment affecter la valeur à quoi que ce soit, comme le chargement de certaines classes une seule fois pendant l'exécution.

par exemple.

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

Hey, il y a un autre avantage, vous pouvez l'utiliser pour gérer les exceptions. Imaginez que getStuff() jette ici un Exception qui vraiment appartient dans un bloc catch:

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

alors un initialiseur static est utile ici. Vous pouvez gérer l'exception là.

Un autre exemple est de faire des choses après qui ne peut être fait au cours de l'affectation:

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);
    }
}

Pour revenir à l'exemple du pilote JDBC, un pilote JDBC décent se fait également l'utilisation de l'initialiseur static s'inscrire dans le DriverManager. Voir aussi cette et cette réponse .

Je dirais que static block est juste du sucre syntaxique. Il n'y a rien que vous pourriez faire avec bloc static et non pas avec quoi que ce soit d'autre.

Pour réutiliser quelques exemples publiés ici.

Ce morceau de code pourrait être réécrite sans utiliser de static initialiseur.

Méthode n ° 1: Avec static

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

Méthode 2: Sans 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;
}

Il y a quelques raisons réelles qu'il est nécessaire d'exister:

  1. membres de static final d'initialisation dont l'initialisation pourrait lancer une exception
  2. initialisant membres de static final avec les valeurs calculées

Les gens ont tendance à utiliser des blocs de static {} comme un moyen pratique pour initialiser les choses que la classe dépend au sein de l'exécution ainsi - comme assurant cette classe particulière est chargé (par exemple, les pilotes JDBC). Cela peut se faire par d'autres moyens; Cependant, les deux choses que je mentionne ci-dessus ne peut être fait avec une construction comme le bloc static {}.

Vous pouvez exécuter des morceaux de code une fois pour une classe avant qu'un objet soit construit dans les blocs statiques.

par exemple.

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());
  }
}

C'est une idée fausse commune à penser qu'un bloc statique a seulement accès à des champs statiques.Pour cela, je voudrais montrons ci-dessous un bout de code que j'ai très souvent utilisés dans le cadre des projets de vie (copié en partie de la une autre réponse dans un contexte légèrement différent):

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); 
  } 
} 

Ici l'initialiseur, est utilisé pour maintenir un index (ALIAS_MAP), à la carte d'un ensemble d'alias à l'origine d'un type enum.Il est conçu comme une extension à la méthode valueOf fournis par le Enum lui-même.

Comme vous pouvez le voir, l'initialiseur statique accède à même le private champ aliases.Il est important de comprendre que l' static bloc a déjà accès à la Enum la valeur des instances (p. ex. ENGLISH).C'est parce que l' ordre de l'initialisation et l'exécution dans le cas de Enum types, comme si la static private les champs ont été initialisé avec les instances devant l' static les blocs ont été appelés:

  1. L' Enum les constantes qui sont implicites champs statiques.Cela nécessite l'Enum constructeur de l'instance et de blocs, et de l'instance, l'initialisation de se produire en premier ainsi.
  2. static bloc et l'initialisation des champs statiques dans l'ordre d'occurrence.

Ce hors-de-l'initialisation de la commande (constructeur avant static block) est important à noter.Il arrive aussi lorsque nous initialiser les champs statiques avec les instances de la même façon à un Singleton (simplifications faites):

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();
  }
}

Ce que nous voyons est la sortie suivante:

Static Block 1
Constructor
Static Block 2
In Main
Constructor

Clair, c'est que l'initialisation statique peut effectivement arriver avant le constructeur, et même après:

Le simple accès Foo dans la méthode main, les causes de la classe de chargement et l'initialisation statique pour commencer.Mais dans le cadre de l'initialisation Statique, nous appelons à nouveau les constructeurs pour les champs statiques, après quoi il reprend initialisation statique, et complète le constructeur appelé à partir de la méthode main.Situation assez complexe pour lequel, je l'espère, dans des conditions normales de codage, nous n'aurions pas à faire face.

Pour plus d'informations sur ce sujet voir le livre "Efficace Java".

Si vos variables statiques doivent être définies lors de l'exécution puis un bloc de static {...} est très utile.

Par exemple, si vous devez définir l'organe statique à une valeur qui est stockée dans un fichier de configuration ou base de données.

Aussi utile lorsque vous souhaitez ajouter des valeurs à un membre de Map statique que vous ne pouvez pas ajouter ces valeurs dans la déclaration de membre initial.

Vous avez donc un champ statique (il est aussi appelé « variable de classe », car il appartient à la classe plutôt qu'à une instance de la classe, en d'autres termes, il est associé à la classe plutôt qu'avec un objet) et que vous voulez initialiser. Donc, si vous ne voulez pas créer une instance de cette classe et que vous voulez manipuler ce champ statique, vous pouvez le faire de trois façons:

1- initialiser Juste quand vous déclarez la variable:

static int x = 3;

2- avoir un bloc d'initialisation statique:

static int x;

static {
 x=3;
}

3- disposer d'une méthode de classe (méthode statique) qui accède à la variable de classe et l'initialise: Telle est l'alternative au bloc statique ci-dessus; vous pouvez écrire une méthode statique privée:

public static int x=initializeX();

private static int initializeX(){
 return 3;
}

Maintenant, pourquoi voulez-vous utiliser le bloc d'initialisation statique au lieu de méthodes statiques?

Il est vraiment à ce que vous avez besoin dans votre programme. Mais vous devez savoir que le bloc d'initialisation statique est appelé une fois le seul avantage de la méthode de classe est qu'ils peuvent être réutilisés plus tard si vous devez réinitialiser la variable de classe.

disons que vous avez un ensemble complexe dans votre programme. Vous lsinitialisez (en utilisant pour boucle par exemple) et les valeurs de ce tableau changeront tout au long du programme mais à un moment donné que vous voulez réinitialiser (revenir à la valeur initiale). Dans ce cas, vous pouvez appeler la méthode statique privée. Si vous n'avez pas besoin dans votre programme pour réinitialiser les valeurs, vous pouvez simplement utiliser le bloc statique et pas besoin d'une méthode statique puisque tu ne vas pas l'utiliser plus tard dans le programme.

Note: les blocs statiques sont appelés dans l'ordre où ils apparaissent dans le code.

Exemple 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
 }

}

Exemple 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
 }

}

Comme supplémentaire, comme @Pointy dit

  

Le code dans la section « statique » (s) sera exécutée à la charge de la classe   temps, avant sont réalisés toutes les instances de la classe (et avant   les méthodes statiques sont appelées d'ailleurs).

Il est censé ajouter System.loadLibrary("I_am_native_library") dans le bloc statique.

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

Il garantira aucune méthode native être appelée avant la bibliothèque associée est chargée en mémoire.

Selon

Vous devez d'abord comprendre que vos cours d'application se sont instanciées à java.class.Class objets lors de l'exécution. Ceci est lorsque vos blocs statiques sont coururent. Ainsi, vous pouvez réellement faire ceci:

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) {
    }

}

et il imprimera "myInt est 1" à la console. Notez que je ne l'ai pas instancié une classe.

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");
    } 
}

bloc statique est utilisé pour toute la technologie pour initialiser le membre de données statiques de manière dynamique, ou nous pouvons dire pour l'initialisation dynamique de membre de données statique bloc statique est d'être used..Because pour l'initialisation de membre de données non statique, nous avons constructeur, mais nous ne pas lieu où l'on peut initialiser dynamiquement membre de données statiques

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);
        }
        }

Maintenant, mon statique int x REINITIALISERA dynamiquement ..Bcoz lorsque le compilateur ira à Solution.x il charge Solution de classe et la charge de bloc statique au chargement de classe time..So nous pouvons en mesure d'initialiser dynamiquement membre de données statiques ..

}

scroll top