Nécessité de bloc statique en Java
J'ai trouvé qu'en Java, il y a une fonctionnalité appelée static block
, qui inclut le code qui est exécuté lorsqu'une classe est chargée pour la première fois (je ne comprends pas ce que "chargé" les moyens, ça veut dire initialisé?). Est-il une raison pour faire l'initialisation de bits à l'intérieur d'un bloc statique et pas dans le constructeur? Je veux dire, même le constructeur fait la même chose, faire toutes les choses nécessaires lorsqu'une classe est d'abord initialisé. est-il rien de statique bloc qui accomplit un constructeur ne peut pas?
- Appelé dès que la classe est chargée par le chargeur de classes. Pas à chaque fois que la classe est instanciée.
- S'il vous plaît, jetez un oeil à les chapitres suivants de l'Officiel Tutoriel Java (Oracle): Compréhension de l'Instance et les Membres de la Classe et Initialisation des Champs. Revenir si vous avez encore des doutes.
- Seulement un non-sequitur question, si une classe arrive à avoir les deux
main
et un constructeur, qui est invoqué précédemment lorsqu'une instance de la classe est créée? - Code d'initialisation (Classloading temps) -> Main (Application point d'entrée) -> Constructeurs: Voici un exemple pour illustrer le point.
- Pour l'exemple que vous avez fournies, pourquoi n'est-il pas de tomber dans une récursion infinie? Je veux dire, la première fois que la classe
Main
est invoquée, la statique bloc est exécuté tout droit. Mais depuis leMain
classe est elle-même à nouveau invoquée à l'intérieur de lamain
méthode, ils vont créer de nouvelles instances deMain
. Tout en étant instancié, la statique bloc ne sera pas exécuté, mais leurmain
méthodes d'exécution, la création de deux nouvelles instances, et ainsi de suite. - Une classe est chargé et initialisé (y compris l'exécution de tout
static
les blocs et les initialiseurs statiques) avant tout des instances sont créées. (Cela peut être déclenchée par la tentative de créer une instance, mais c'est un processus distinct de la création de l'instance.) Plus tard lorsque vous créer des instances de cette classe, les blocs statiques ne sont pas exécutées à nouveau (il en va de même pour les initialiseurs statiques). Ainsi il n'y aura pas de récursivité pour une classe avec unstatic
bloc etmain
méthode. - Le
main
méthode est de ne pas exécuter à chaque fois qu'une instance d'une classe est créée. C'est uniquement lorsque explicitement invoqué (comme toute autre méthode statique) ou lorsque la JVM commence l'application. - Juste la création d'une instance d'une classe avec une méthode main ne sera pas l'appeler. Rappelez-vous que la principale méthode est un
static
point d'entrée qui sera exécuté implicity par la JVM une fois. Alors vous avez certainement peut invoquer lamain
méthode explicitement et même dans un de manière récursive mode, il a définitivement sonne comme une mauvaise idée :). - Ressemble à une copie de stackoverflow.com/questions/2420389/...
- Quelqu'un peut-il expliquer ce qu'on entend par "chargé"? Comment est-il différent de "initialisé'?
- C'est tous les énoncés en détail sanglant dans Chapitre 5 de la Machine Virtuelle Java Specification. Grosso modo, le "chargement" est la lecture de l'octet codes dans la mémoire lorsque "initialisé" signifie que le code d'initialisation de la classe est exécutée.
- Je passais par le Chapitre 12 à docs.oracle.com/javase/specs/jls/se7/html/..., et je ne pouvais pas déchiffrer la tête et la queue de il. Pouvez-vous m'indiquer une meilleure ressource qui parle tout autant à la longueur, mais beaucoup plus de lucidité, et si possible, avec un certain nombre d'exemples?
- Google est votre ami ici. Ce sujet est compliqué, donc ne vous attendez pas quelque chose qui est facile à digérer. Cette introduction sur le sujet peut-être ce que vous cherchez.
- Ouais, il a l'air vraiment compliqué. Va me prendre tout à fait un peu d'effort et de temps pour digérer tout ça..
Vous devez vous connecter pour publier un commentaire.
Si une classe a des membres statiques qui nécessitent une initialisation complexe, un
static
bloc est l'outil à utiliser. Supposons que vous avez besoin d'une carte statique quelconque (le but n'est pas pertinent ici). Vous pouvez déclarer en ligne comme ceci:Toutefois, si vous voulez remplir une fois, vous ne pouvez pas faire cela avec une ligne de déclaration. Pour cela, vous avez besoin d'un
static
bloc:Si vous voulez être encore plus de protection, vous pouvez le faire:
Notez que vous ne pouvez pas initialiser
initials
en ligne inmodifiable carte, car alors vous ne pouvez pas le remplir! Vous ne pouvez pas faire cela dans un constructeur parce que tout simplement d'appeler l'une des méthodes de modification (put
, etc.) va générer une exception.Pour être juste, ce n'est pas une réponse complète à votre question. Le
static
bloc pourrait encore être éliminés en utilisant une private static function:Noter, cependant, que ce n'est pas le remplacement d'un
static
bloc de code dans un constructeur que vous avez proposé! Aussi, cela ne fonctionnera pas si vous avez besoin d'initialiser plusieursstatic
champs dans un même chemin.Un cas où un
static
bloc serait difficile à remplacer serait un "maître" de la classe qui doit initialiser plusieurs autres classes exactement une fois.En particulier si vous ne voulez pas dur de fil de dépendance dans
SlaveClass2
surSlaveClass1
, une sorte de maître de code comme celui-ci est nécessaire. Ce genre de trucs très certainement n'appartient pas à un constructeur.Remarque qu'il y a aussi quelque chose appelé un instance d'initialiseur bloc. C'est un anonyme, un bloc de code qui est exécuté lors de chaque instance est créée. (La syntaxe est juste comme un
static
bloc, mais sans lestatic
mot-clé.) Il est particulièrement utile pour les classes, parce qu'ils ne peuvent pas avoir nommé des constructeurs. Voici un exemple réel. Depuis (exceptionnellement)GZIPOutputStream
ne possède pas de constructeur ou de tout appel d'api qui vous permet de spécifier le niveau de compression, et le niveau de compression par défaut est none, vous avez besoin de sous-classeGZIPOutputStream
pour obtenir une compression. Vous pouvez toujours écrire explicitement la sous-classe, mais il peut être plus commode d'écrire une classe anonyme:java.lang.Math
ne contient que des méthodes statiques et n'est jamais instanciée par exemple. (Bien queMath
contient un constructeur, mais curieusement que le constructeur est là pour s'assurer qu'aucune des instances sont créées.)static { System.loadLibrary ("foo"); }
static
etfinal
(de sorte qu'il ne peut pas être changé), la langue ne vous permettra pas de le faire dans le constructeur.static final
domaine à partir d'un constructeur. Et c'est une dure limite, votre code ne sera tout simplement pas compiler. Mais vous pouvez facilement avoir des classes qui ont un seul videprivate
constructeur pour empêcher l'instanciation. Même si vous mettez le code, il ne sera jamais appelé. (Comme c'estprivate
, personne ne peut le voir.)final
implique que, d'ailleurs, pardonne-moi donc mon mutisme)?final
variable doit être "définitivement attribué" une valeur exactement une fois. Si il n'y a pas d'affectation, ou (dans la mesure où le compilateur ne peut pas savoir) une chance que la cession ne sera pas exécuté ou sera exécuté plus d'une fois, il va générer une erreur. La méthodeCollections.unmodifiableMap
n'a rien à voir avecfinal
; il prend toutMap
et la transforme en une autreMap
qui va générer une exception à l'exécution de toute tentative d'ajouter, de modifier ou de supprimer une entrée dans la carte. Lors de l'utilisation de deuxfinal
et inmodifiable, unstatic
bloc est indispensable.Constructeur est appelé lors de la création d'une instance de la classe.
Statique bloc est appelé lorsque un chargeur de classe des charges de la définition de cette classe, de sorte que nous pouvons initialiser les membres statiques de la classe.
Nous ne devrions pas être initialisation statique membres de constructeur, car ils font partie de la définition de la classe pas l'objet
static
champ dans un constructeur. Cette technique est utilisée, par exemple, pour générer un identifiant unique pour chaque instance d'une classe: définir, disons, unprivate static int nextID
champ, initialisé (statiquement) à 0, puis dans le constructeur attribuerthis.id = nextID++;
.Initialiseur statique d'exécution si nous initialisons une classe, cela ne nécessite pas que nous instancier une classe. Mais le constructeur est exécuté que lorsque nous faisons une instance de la classe.
Par exemple:
Si nous lancer:
De sortie:
Nous n'avons jamais créé une instance de sorte que le constructeur n'est pas appelé, mais initialiseur statique est appelé.
Si nous faisons une instance d'une classe, à la fois statique initilizer et le constructeur exécuter. Pas de surprises.
De sortie:
Noter que si l'on effectue:
De sortie: (vide)
Déclarant la variable
x
ne nécessite pas deMyClass
être initialisé, afin d'initialiseur statique ne fonctionne pas.MyClass x
n'exige pas que la classe soit chargé ou initialisé. Java est assez intelligent pour savoir qu'il peut différer le chargement et l'initialisation de la classe jusqu'à ce que quelque chose (autre que c'est son nom) n'est pas réellement nécessaire. (En passant, il suffit de référencement d'un champ statique de la classe peut aussi causer la classe d'être initialisé. Vous n'avez pas besoin de créer une instance ou d'appel d'une méthode.)MyClass
n'est pas créé, tandis que le constructeur ne l'est pas. C'est quelque chose que l'initialiseur statique peut le faire, et le constructeur ne peut pas faire.L'initialiseur statique fonctionne que lorsque la classe est chargée, même si vous n'avez jamais créer des objets de ce type.
Vous ne pouvez pas initialiser des variables statiques, avec un constructeur, ou, au moins, vous avez probablement ne devrait pas, et il ne sera pas particulièrement utile.
En particulier lorsque vous essayez d'initialiser les constantes statiques qui nécessitent beaucoup de logique pour générer, qui devrait arriver dans un bloc statique, pas un constructeur.
Ils sont deux choses distinctes. Vous utilisez un constructeur pour initialiser une instance d'une classe, l'initialisation statique bloc d'initialisation statique membres à la fois que la classe est chargé.
La statique bloc est reqly utile lorsque vous avez à faire un peu d'action, même si aucun cas n'est encore créé. À titre d'exemple, pour l'initialisation d'une variable statique non statique de la valeur.
statique bloc n'est autre chose que constructeur . Fondamentalement, il n'y sre de deux concepts différents.
statique bloc initialise lors de la classe de charge en mémoire , cela signifie que, lorsque la JVM lire u r de byte code.
L'initialisation ne peut quoi que ce soit , il peut être l'initialisation d'une variable ou toute autre chose qui doit être partagée par tous les objets de cette classe
alors que le constructeur initialise la variable pour cet objet .
La statique bloc est utile lorsque vous souhaitez initialiser les champs statiques.
La statique bloc est utile au cours de constructeurs quand vous avez à faire un peu d'action, même si aucun cas n'est encore créé. À titre d'exemple, pour l'initialisation d'une variable statique non statique de la valeur.
Une façon, vous pouvez comprendre statique bloc de l'est;
Il agit comme un constructeur. cependant, la différence entre les deux est
statique bloc instancie la classe ou de variables statiques alors que le constructeur est utilisé pour instancier les variables d'objet
Considérer la classe suivante
objets créés à partir de cette classe aura producteur mis à Boeing, mais leur nom est différent en fonction de l'argument passé. par exemple