2010-03-30 5 views

Répondre

4

Comme discuté par d'autres réponses, non, cela ne peut pas arriver. Avec un champ statique final assigné, cependant, il le peut.

class MyClass { 
    private static MyClass myClass = new MyClass(); 
    private static final Object obj = new Object(); 
    public MyClass() { 
    System.out.println(obj); // will print null once 
    } 
} 
+1

Merci! Et cela conduit à http://stackoverflow.com/questions/2547713/why-static-fields-are-not-initialized-in-time –

+0

Ceci est d'il y a longtemps, mais je veux juste dire que même si cela peut Ça n'arrive pas, ça me concerne. La seule chose que je peux penser est que c'est parce que c'est GWT que j'ai affaire, donc c'est Java qui est compilé avec JScript. – Jamie

2

L'initialiseur Object obj = new Object(); s'exécutera avant le code dans le constructeur, donc obj ne peut pas être null.

Notez que cela ne compilera pas si vous n'initialisez obj nulle part.

2

Works pour moi:

$ cat MyClass.java 
class MyClass { 
    private final Object obj = new Object(); 
    public MyClass() { 
     System.out.println(obj); // may print null? 
    } 
    public static void main(String[] args) { new MyClass(); } 
} 
$javac MyClass.java; java MyClass 
[email protected] 

Tous les initialiseurs de terrain sont copiés par le compilateur dans le début de tous les constructeurs.

Cependant, dans le cadre du modèle de mémoire Java 5, si vous laissez la référence this « évasion » avant la fin du constructeur, d'autres threads peuvent voir les valeurs non initialisées de champs final (donc pu voir null dans ce cas).

+0

Ce n'était pas mon négatif, mais de quoi parlez-vous? –

+0

Le dernier paragraphe décrit la seule situation que je connais où il est possible de voir la valeur d'un champ final ayant sa valeur non initialisée. Voir le "Comment les champs finaux fonctionnent sous le nouveau JMM?" section de http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html –

+0

+1 - voir aussi https://www.securecoding.cert.org/confluence/pages/ viewpage.action? pageId = 32833640 –

3

Ce n'est pas possible que le tout comme initializers run before the constructor is invoked.

initializers variables comme vous avez private final Object obj = new Object(); courir avant que le constructeur est invoqué. Ceci est également vrai pour les blocs d'initialisation statiques ou non. Une chose à surveiller lors de l'utilisation des initialiseurs est que les initialiseurs ne peuvent pas faire de références avant Lorsque vous écrivez un initialiseur, vous ne pouvez pas faire référence à des variables d'instance déclarées textuellement après l'initialisation de la variable.

2

Avec un exemple simple comme le vôtre, rien de mauvais ne peut arriver. Cependant, est possible pour qu'un champ final soit visible comme non initialisé si vous utilisez des pratiques douteuses comme l'appel d'une méthode remplaçable dans votre constructeur. Par exemple, le programme suivant imprime "Ma couleur préférée est nulle", même s'il fait référence à la variable finale favouriteColour, qui est définie sur "blue" dans le constructeur.

abstract class SuperClass { 
    final String favouriteColour; 

    SuperClass() { 
     announceFavouriteColour(); 
     favouriteColour = "blue"; 
    } 

    abstract void announceFavouriteColour(); 
} 

public class FinalTest extends SuperClass { 
    void announceFavouriteColour() { 
     System.out.println("My favourite colour is " + favouriteColour); 
    } 

    public static void main(String[] args) { 
     new FinalTest(); 
    } 
} 
Questions connexes