J'ai trouvé qu'en Java, il existe une fonctionnalité appelée static block
, qui comprend du code qui est exécuté lors du premier chargement d'une classe (je ne comprends pas ce que signifie "chargé", cela signifie-t-il initialisé?). Y a-t-il une raison de faire le bit d'initialisation à l'intérieur d'un bloc statique et non dans le constructeur? Je veux dire, même le constructeur fait la même chose, faites tout le nécessaire quand une classe est initialisée pour la première fois. y a-t-il quelque chose que le bloc statique accomplit qu'un constructeur ne peut pas?
Si une classe a des membres statiques qui nécessitent une initialisation complexe, un bloc static
est l'outil à utiliser. Supposons que vous ayez besoin d'une carte statique quelconque (le but n'est pas pertinent ici). Vous pouvez le déclarer en ligne comme ceci:
public static final Map<String, String> initials = new HashMap<String, String>();
Cependant, si vous souhaitez le remplir une fois, vous ne pouvez pas le faire avec une déclaration en ligne. Pour cela, vous avez besoin d'un bloc static
:
public static final Map<String, String> initials = new HashMap<String, String>();
static {
initials.put("AEN", "Alfred E. Newman");
// etc.
}
Si vous vouliez être encore plus protecteur, vous pouvez le faire:
public static final Map<String, String> initials;
static {
HashMap<String, String> map = new HashMap<String, String>()
map.put("AEN", "Alfred E. Newman");
// etc.
initials = Collections.unmodifiableMap(map);
}
Notez que vous ne pouvez pas initialiser initials
en ligne comme une carte non modifiable car vous ne pourriez pas la remplir! Vous ne pouvez pas non plus le faire dans un constructeur car le simple fait d'appeler l'une des méthodes de modification (put
, etc.) générera une exception.
Pour être juste, ce n'est pas une réponse complète à votre question. Le bloc static
pourrait toujours être éliminé en utilisant une fonction statique privée:
public static final Map<String, String> initials = makeInitials();
private static Map<String, String> makeInitials() {
HashMap<String, String> map = new HashMap<String, String>()
map.put("AEN", "Alfred E. Newman");
// etc.
return Collections.unmodifiableMap(map);
}
Notez cependant que cela ne remplace pas un bloc static
par du code dans un constructeur comme vous l'avez proposé!
Un cas où un bloc static
serait difficile à remplacer serait une classe "maître" qui doit initialiser plusieurs autres classes exactement une fois.
public class Master {
static {
SlaveClass1.init();
SlaveClass2.init(SlaveClass1.someInitializedValue);
// etc.
}
}
Surtout si vous ne voulez pas câbler en dur une dépendance dans SlaveClass2
sur SlaveClass1
, une sorte de code maître comme celui-ci est nécessaire. Ce genre de choses n'appartient certainement pas à un constructeur.
Notez qu'il existe également quelque chose appelé bloc d'initialisation d'instance. Il s'agit d'un bloc de code anonyme qui est exécuté lors de la création de chaque instance. (La syntaxe ressemble à un bloc static
, mais sans le mot clé static
.) Elle est particulièrement utile pour les classes anonymes, car elles ne peuvent pas avoir de constructeurs nommés. Voici un exemple concret. Puisque (insondable) GZIPOutputStream
n'a pas de constructeur ni d'appel API avec lequel vous pouvez spécifier un niveau de compression, et le niveau de compression par défaut est aucun, vous devez sous-classer GZIPOutputStream
pour obtenir une compression . Vous pouvez toujours écrire une sous-classe explicite, mais il peut être plus pratique d'écrire une classe anonyme:
OutputStream os = . . .;
OutputStream gzos = new GZIPOutputStream(os) {
{
// def is an inherited, protected field that does the actual compression
def = new Deflator(9, true); // maximum compression, no ZLIB header
}
};
Le constructeur est appelé lors de la création d'une instance de la classe.
Le bloc statique est invoqué lorsqu'un chargeur de classe charge cette définition de classe, afin que nous puissions initialiser les membres statiques de cette classe. Nous ne devrions pas initialiser les membres statiques du constructeur car ils font partie de la définition de classe et non d'objet
L'initialiseur statique s'exécutera si nous initialisons une classe, cela ne nécessite pas que nous instancions une classe. Mais le constructeur n'est exécuté que lorsque nous créons une instance de la classe.
Par exemple:
class MyClass
{
static
{
System.out.println("I am static initializer");
}
MyClass()
{
System.out.println("I am constructor");
}
static void staticMethod()
{
System.out.println("I am static method");
}
}
Si nous courons:
MyClass.staticMethod();
Production:
I am static initializer
I am static method
Nous n'avons jamais créé d'instance, le constructeur n'est donc pas appelé, mais un initialiseur statique est appelé.
Si nous créons une instance d'une classe, l'initiateur statique et le constructeur s'exécutent. Pas de surprises.
MyClass x = new MyClass();
Production:
I am static initializer
I am constructor
Notez que si nous exécutons:
MyClass x;
Sortie: (vide)
La déclaration de la variable x
ne nécessite pas l'initialisation de MyClass
, donc l'initialisation statique ne s'exécute pas.
L'initialiseur statique s'exécute lorsque la classe est chargée même si vous ne créez jamais d'objets de ce type.
Vous ne pouvez pas initialiser des variables statiques avec un constructeur - ou du moins, vous ne devriez pas, et ce ne sera pas particulièrement utile.
Surtout lorsque vous essayez d'initialiser des constantes statiques qui nécessitent une logique importante pour générer, cela devrait vraiment se produire dans un bloc statique, pas dans un constructeur.
le bloc statique fait autre chose que le constructeur. Fondamentalement, il existe deux concepts différents.
le bloc statique s'initialise lorsque la classe se charge en mémoire, cela signifie que la JVM lit le code d'octet u'r. L'initialisation ne peut rien, elle peut être une initialisation variable ou toute autre chose qui devrait être partagée par tous les objets de cette classe
tandis que le constructeur initialise la variable pour cet objet uniquement.
Ce sont deux choses distinctes. Vous utilisez un constructeur pour initialiser une instance d'une classe, le bloc d'initialisation statique initialise les membres statiques au moment du chargement de la classe.
Le bloc statique est très utile lorsque vous devez effectuer une action même si aucune instance n'est encore créée. Par exemple, pour initialiser une variable statique avec une valeur non statique.
Le bloc statique est utile lorsque vous souhaitez initialiser des champs statiques.
Le bloc statique est utile par rapport aux constructeurs lorsque vous devez effectuer une action même si aucune instance n'est encore créée. Par exemple, pour initialiser une variable statique avec une valeur non statique.
Une façon de comprendre le blocage statique est; Il agit comme un constructeur. cependant, la différence entre les deux est le bloc statique instancie la classe ou les variables statiques tandis que le constructeur est utilisé pour instancier les variables d'objet
Considérez la classe suivante
public class Part{
String name;
static String producer;
public Part(String name){
this.name = name;
}
static {
producer = "Boeing";
}
}
les objets créés à partir de cette classe auront le producteur défini sur Boeing mais leur nom est différent selon l'argument passé. par exemple
Part engine = new Part("JetEngine");
Part Wheel = new Part("JetWheel");