Pour autant que je sache, le "bloc d'initialisation statique" est utilisé pour définir les valeurs du champ statique s'il ne peut pas être effectué sur 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 attribution de valeur). Ensuite, écrivez plusieurs lignes du code qui génèrent et affectent une valeur au champ statique déclaré ci-dessus.
Pourquoi avons-nous besoin de ces lignes dans un bloc spécial comme static {...}
:?
{...}
vsstatic {...}
. (auquel cas Jon Skeet a définitivement mieux répondu à votre question)Réponses:
Le bloc non statique:
Obtient appelé chaque fois qu'une instance de la classe est construite. Le bloc statique n'est appelé qu'une seule fois , lorsque la classe elle-même est initialisée, quel que soit le nombre d'objets de ce type que vous créez.
Exemple:
Cela imprime:
la source
S'ils n'étaient pas dans un bloc d'initialisation statique, où seraient-ils? Comment déclareriez-vous une variable qui était uniquement destinée à être locale à des fins d'initialisation et la distingueriez-vous d'un champ? Par exemple, comment voudriez- vous écrire:
Si
first
etsecond
n'étaient pas dans un bloc, ils ressembleraient à des champs. S'ils étaient dans un bloc sansstatic
en face de lui, cela compterait comme un bloc d'initialisation d'instance au lieu d'un bloc d'initialisation statique, il serait donc exécuté une fois par instance construite plutôt qu'une fois au total.Maintenant, dans ce cas particulier, vous pouvez utiliser une méthode statique à la place:
... mais cela ne fonctionne pas lorsqu'il y a plusieurs variables que vous souhaitez affecter dans le même bloc, ou aucune (par exemple si vous voulez simplement enregistrer quelque chose - ou peut-être initialiser une bibliothèque native).
la source
private static int widgets = 0; static{widgets = 2;}
private static int widgets = 0; static{widgets = 2;}
j'ai découvert que l'affectation «=» se produit dans l'ordre, ce qui signifie que le «=» mis en premier sera attribué en premier. L'exemple ci-dessus donnera aux 'widgets' une valeur de 2. (PS ne savait pas que les commentaires ne peuvent être modifiés qu'en 5 min ...)Voici un exemple:
Le code de la ou des sections "statiques" sera exécuté au moment du chargement de la classe, avant que des instances de la classe ne soient construites (et avant que des méthodes statiques soient appelées ailleurs). De cette façon, vous pouvez vous assurer que les ressources de classe sont toutes prêtes à être utilisées.
Il est également possible d'avoir des blocs d'initialisation non statiques. Celles-ci agissent comme des extensions de l'ensemble des méthodes constructeurs définies pour la classe. Ils ressemblent à des blocs d'initialisation statiques, sauf que le mot clé "statique" est laissé de côté.
la source
Il est également utile lorsque vous ne voulez en fait affecter la valeur à rien, comme le chargement d'une classe une seule fois pendant l'exécution.
Par exemple
Hé, il y a un autre avantage, vous pouvez l'utiliser pour gérer les exceptions. Imaginez
getStuff()
qu'ici lance unException
qui appartient vraiment à un bloc catch:puis un
static
initialiseur est utile ici. Vous pouvez gérer l'exception ici.Un autre exemple est de faire ensuite des choses qui ne peuvent pas être faites pendant l'attribution:
Pour revenir à l'exemple du pilote JDBC, tout pilote JDBC décent utilise lui-même l'
static
initialiseur pour s'enregistrer dans leDriverManager
. Voir aussi ceci et cette réponse.la source
Je dirais que
static block
c'est juste du sucre syntaxique. Il n'y a rien que vous puissiez faire avec unstatic
bloc et rien d'autre.Pour réutiliser certains exemples publiés ici.
Ce morceau de code pourrait être réécrit sans utiliser d'
static
initialiseur.Méthode n ° 1: avec
static
Méthode n ° 2: sans
static
la source
Il y a quelques raisons réelles pour lesquelles il doit exister:
static final
membres dont l'initialisation pourrait lever une exceptionstatic final
membres avec des valeurs calculéesLes gens ont tendance à utiliser les
static {}
blocs comme un moyen pratique d'initialiser les éléments dont la classe dépend également au cours de l'exécution - comme s'assurer qu'une classe particulière est chargée (par exemple, les pilotes JDBC). Cela peut se faire par d'autres moyens; cependant, les deux choses que je mentionne ci-dessus ne peuvent être faites qu'avec une construction comme lestatic {}
bloc.la source
Vous pouvez exécuter des bits de code une fois pour une classe avant de construire un objet dans les blocs statiques.
Par exemple
la source
Il est faux de penser qu'un bloc statique n'a accès qu'aux champs statiques. Pour cela, je voudrais montrer ci-dessous un morceau de code que j'utilise assez souvent dans des projets réels (copié partiellement à partir d' une autre réponse dans un contexte légèrement différent):
Ici, l'initialiseur est utilisé pour maintenir un index (
ALIAS_MAP
), pour mapper un ensemble d'alias au type d'énumération d'origine. Il est conçu comme une extension de la méthode intégrée valueOf fournie par leEnum
lui même.Comme vous pouvez le voir, l'initialiseur statique accède même au
private
champaliases
. Il est important de comprendre que lestatic
bloc a déjà accès auxEnum
instances de valeur (par exempleENGLISH
). En effet, l' ordre d'initialisation et d'exécution dans le cas desEnum
types , comme si lesstatic private
champs avaient été initialisés avec des instances avant l'static
appel des blocs:Enum
constantes qui sont des champs statiques implicites. Cela nécessite le constructeur Enum et les blocs d'instance, et l'initialisation d'instance doit également se produire en premier.static
bloc et initialisation des champs statiques dans l'ordre d'apparition.Cette initialisation désordonnée (constructeur avant
static
bloc) est importante à noter. Cela se produit également lorsque nous initialisons des champs statiques avec les instances de manière similaire à un singleton (simplifications apportées):Ce que nous voyons est la sortie suivante:
Il est clair que l'initialisation statique peut réellement se produire avant le constructeur, et même après:
Le simple accès à Foo dans la méthode principale provoque le chargement de la classe et le démarrage de l'initialisation statique. Mais dans le cadre de l'initialisation statique, nous appelons à nouveau les constructeurs des champs statiques, après quoi il reprend l'initialisation statique et termine le constructeur appelé depuis la méthode principale. Situation assez complexe pour laquelle j'espère qu'en codage normal nous n'aurions pas à faire face.
Pour plus d'informations à ce sujet, consultez le livre " Java efficace ".
la source
aliases
ne signifie pas que le bloc statique peut accéder aux membres non statiques.aliases
est accessible via lesLanguage
valeurs renvoyées par lavalues()
méthode / static / . Comme vous le mentionnez, le fait que les variables enum soient déjà disponibles à ce stade est le bit inhabituel - les membres non statiques des classes régulières ne seraient pas accessibles dans cette situation.class Foo { static final Foo Inst1; static final Foo Inst2; static{ Inst1 = new Foo("Inst1"); Inst2 = new Foo("Inst2"); } static { System.out.println("Inst1: " + Inst1.member); System.out.println("Inst2: " + Inst2.member); } private final String member; private Foo(String member){ this.member = member; } }
Le code ci-dessus n'est pas différent de l'exemple enum et permet toujours l'accès à la variable d'instance à l'intérieur du bloc statiqueEnum
. C'est le meilleur moyen de garantir que nous pointons vers des instances singulières »- voir ici . Et à vos points, j'ai fait plusieurs mises à jour.Si vos variables statiques doivent être définies lors de l'exécution, un
static {...}
bloc est très utile.Par exemple, si vous devez définir le membre statique sur une valeur qui est stockée dans un fichier de configuration ou une base de données.
Également utile lorsque vous souhaitez ajouter des valeurs à un
Map
membre statique car vous ne pouvez pas ajouter ces valeurs dans la déclaration de membre initiale.la source
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'à n'importe quel objet) et vous souhaitez l'initialiser. Donc, si vous ne voulez PAS créer une instance de cette classe et que vous souhaitez manipuler ce champ statique, vous pouvez le faire de trois manières:
1- Il suffit de l'initialiser lorsque vous déclarez la variable:
2- Avoir un bloc d'initialisation statique:
3- Avoir une méthode de classe (méthode statique) qui accède à la variable de classe et l'initialise: c'est l'alternative au bloc statique ci-dessus; vous pouvez écrire une méthode statique privée:
Maintenant, pourquoi utiliseriez-vous un bloc d'initialisation statique au lieu de méthodes statiques?
Cela dépend vraiment de ce dont vous avez besoin dans votre programme. Mais vous devez savoir que le bloc d'initialisation statique est appelé une fois et le seul avantage de la méthode de classe est qu'il peut être réutilisé plus tard si vous devez réinitialiser la variable de classe.
disons que vous avez un tableau complexe dans votre programme. Vous l'initialisez (en utilisant pour loop par exemple), puis les valeurs de ce tableau changeront tout au long du programme, mais à un moment donné, vous voudrez le réinitialiser (revenir à la valeur initiale). Dans ce cas, vous pouvez appeler la méthode statique privée. Dans le cas où vous n'avez pas besoin de réinitialiser les valeurs dans votre programme, vous pouvez simplement utiliser le bloc statique et pas besoin d'une méthode statique car vous ne l'utiliserez pas plus tard dans le programme.
Remarque: les blocs statiques sont appelés dans l'ordre dans lequel ils apparaissent dans le code.
Exemple 1:
Exemple 2:
la source
Comme supplémentaire, comme l'a dit @Pointy
Il est censé s'ajouter
System.loadLibrary("I_am_native_library")
au bloc statique.Il garantira qu'aucune méthode native ne sera appelée avant que la bibliothèque associée ne soit chargée en mémoire.
Selon loadLibrary d'Oracle :
Donc, de manière assez inattendue, mettre System.loadLibrary n'est pas utilisé pour éviter que la bibliothèque soit chargée plusieurs fois.
la source
Vous devez d'abord comprendre que vos classes d'application elles-mêmes sont instanciées aux
java.class.Class
objets pendant l'exécution. C'est à ce moment que vos blocs statiques sont exécutés. Vous pouvez donc réellement faire ceci:et il afficherait "myInt is 1" sur la console. Notez que je n'ai instancié aucune classe.
la source
la source
le bloc statique est utilisé pour toute technologie pour initialiser un membre de données statiques de manière dynamique, ou nous pouvons dire que pour l'initialisation dynamique du membre de données statiques, un bloc statique est utilisé. tout endroit où nous pouvons initialiser dynamiquement un membre de données statiques
Maintenant, mon int x statique s'initialisera dynamiquement .. Bcoz lorsque le compilateur ira à Solution.x il chargera la classe de solution et la charge de bloc statique au moment du chargement de la classe .. Nous pouvons donc initialiser dynamiquement ce membre de données statiques ..
}
la source