Voici mon code:
class A {
static A obj = new A();
static int num1;
static int num2=0;
private A() {
num1++;
num2++;
}
public static A getInstance() {
return obj;
}
}
public class Main{
public static void main(String[] arg) {
A obj = A.getInstance();
System.out.println(obj.num1);
System.out.println(obj.num2);
}
}
Le résultat est 1 0
, mais je ne peux pas comprendre.
Quelqu'un peut-il me l'expliquer?
Réponses:
En Java, deux phases ont lieu: 1. Identification, 2. Exécution
En phase d' identification , toutes les variables statiques sont détectées et initialisées avec des valeurs par défaut.
Alors maintenant, les valeurs sont:
A obj=null
num1=0
num2=0
La deuxième phase, l' exécution , commence de haut en bas. En Java, l'exécution commence à partir des premiers membres statiques.
Ici, votre première variable statique est
static A obj = new A();
, donc d'abord elle créera l'objet de cette variable et appellera le constructeur, d'où la valeur denum1
etnum2
devient1
.Et puis, à nouveau,
static int num2=0;
sera exécuté, ce qui faitnum2 = 0;
.Maintenant, supposons que votre constructeur ressemble à ceci:
Cela lancera un
NullPointerException
carobj
n'a toujours pas de référenceclass A
.la source
static A obj = new A();
cistatic int num2=0;
- dessous et vous devriez obtenir 1 et 1.A obj = new A(); int num1; int num2 = 0;
Obtient transformé en ceci:A obj; int num1; int num2; obj = new A(); num2 = 0;
. Java fait cela etnum1, num2
sont définis par le moment où vous atteignez lenew A()
constructeur.Ce que
static
signifie le modificateur lorsqu'il est appliqué à une déclaration de variable, c'est que la variable est une variable de classe plutôt qu'une variable d'instance. En d'autres termes ... il n'y a qu'une seulenum1
variable et une seulenum2
variable.(A part: une variable statique est comme une variable globale dans d'autres langages, sauf que son nom n'est pas visible partout. Même s'il est déclaré comme a
public static
, le nom non qualifié n'est visible que s'il est déclaré dans la classe courante ou dans une superclasse , ou s'il est importé à l'aide d'une importation statique. C'est la distinction. Un vrai global est visible sans qualification n'importe où.)Donc , lorsque vous parlez
obj.num1
etobj.num2
, vous faites référence réellement les variables statiques dont les désignations sont réellesA.num1
etA.num2
. Et de même, lorsque le constructeur incrémentenum1
etnum2
, il incrémente les mêmes variables (respectivement).La ride déroutante dans votre exemple est dans l'initialisation de la classe. Une classe est initialisée en initialisant d'abord par défaut toutes les variables statiques, puis en exécutant les initialiseurs statiques déclarés (et les blocs d'initialisation statiques) dans l'ordre dans lequel ils apparaissent dans la classe. Dans ce cas, vous avez ceci:
Cela se passe comme ceci:
Les statiques commencent avec leurs valeurs initiales par défaut;
A.obj
estnull
etA.num1
/A.num2
sont zéro.La première déclaration (
A.obj
) crée une instance deA()
, et le constructeur pour lesA
incrémentsA.num1
etA.num2
. Lorsque la déclaration se termine,A.num1
etA.num2
sont les deux1
, etA.obj
fait référence à l'A
instance nouvellement construite .La deuxième déclaration (
A.num1
) n'a pas d'initialiseur, doncA.num1
ne change pas.La troisième déclaration (
A.num2
) a un initialiseur qui affecte zéro àA.num2
.Ainsi, à la fin de l'initialisation de la classe,
A.num1
est1
etA.num2
est0
... et c'est ce que montrent vos instructions d'impression.Ce comportement déroutant est en fait dû au fait que vous créez une instance avant la fin de l'initialisation statique et que le constructeur que vous utilisez dépend et modifie une statique qui doit encore être initialisée. C'est quelque chose que vous devriez éviter de faire dans du vrai code.
la source
1,0 est correct.
Lorsque la classe est chargée, toutes les données statiques sont initialisées ou déclarées. Par défaut, int est égal à 0.
static int num1;
ne fait rienstatic int num2=0;
cela écrit 0 à num2la source
Cela est dû à l'ordre des initialiseurs statiques. Les expressions statiques dans les classes sont évaluées dans un ordre descendant.
Le premier à être appelé est le constructeur de
A
, qui définitnum1
et lesnum2
deux à 1:static A obj = new A();
Ensuite,
est appelé et définit à nouveau num2 = 0.
C'est pourquoi
num1
vaut 1 etnum2
0.En remarque, un constructeur ne doit pas modifier les variables statiques, c'est une très mauvaise conception. Au lieu de cela, essayez une approche différente pour implémenter un Singleton en Java .
la source
Une section dans JLS peut être trouvée: §12.4.2 .
Ainsi, les trois variables statiques seront initialisées une par une dans l'ordre textuel.
Alors
Si je change la commande en:
Le résultat sera
1,1
.Notez que le
static int num1;
n'est pas un initialiseur de variable car ( §8.3.2 ):Et cette variable de classe est initialisée lorsque la classe est créée. Cela se produit en premier ( §4.12.5 ).
la source
Peut-être que cela aidera à y penser de cette façon.
Les classes sont des plans pour les objets.
Les objets peuvent avoir des variables lorsqu'ils sont instanciés.
Les classes peuvent également avoir des variables. Ceux-ci sont déclarés statiques. Ils sont donc définis sur la classe plutôt que sur les instances d'objet.
Vous ne pouvez avoir qu'une seule classe dans une application, c'est donc un peu comme un stockage global spécifiquement pour cette classe. Ces variables statiques peuvent bien sûr être accédées et modifiées de n'importe où dans votre application (en supposant qu'elles soient publiques).
Voici un exemple de classe "Dog" qui utilise une variable statique pour suivre le nombre d'instances qu'elle a créées.
La classe "Dog" est le cloud tandis que les boîtes orange sont des instances "Dog".
Lire la suite
J'espère que cela t'aides!
Si vous avez envie de questions, cette idée a été introduite pour la première fois par Platon
la source
Le mot-clé static est utilisé en java principalement pour la gestion de la mémoire. Nous pouvons appliquer un mot-clé statique avec des variables, des méthodes, des blocs et une classe imbriquée. Le mot-clé static appartient à la classe plutôt qu'à l'instance de la classe.Pour une brève explication sur le mot-clé static:
http://www.javatpoint.com/static-keyword-in-java
la source
La plupart des réponses ci-dessus sont correctes. Mais vraiment pour illustrer ce qui se passe, j'ai fait quelques petites modifications ci-dessous.
Comme mentionné plusieurs fois ci-dessus, ce qui se passe, c'est qu'une instance de la classe A est créée avant que la classe A ne soit complètement chargée. Donc, ce qui est considéré comme le «comportement» normal n'est pas observé. Ce n'est pas trop différent de l'appel de méthodes à partir d'un constructeur qui peut être remplacé. Dans ce cas, les variables d'instance peuvent ne pas être dans un état intuitif. Dans cet exemple, les variables de classe ne sont pas dans un état intuitif.
La sortie est
la source
java n'initialise pas la valeur d'un membre de données statique ou non statique jusqu'à ce qu'il ne soit pas appelé, mais il le crée.
Donc, ici, lorsque num1 et num2 seront appelés dans main, il sera initialisé avec des valeurs
num1 = 0 + 1; et
num2 = 0;
la source