web-dev-qa-db-fra.com

Comportement des blocs statiques avec héritage

J'essaie d'utiliser des blocs statiques comme ceci:

J'ai une classe de base appelée Base.Java

public class Base {

    static public int myVar;

}

Et une classe dérivée Derived.Java:

public class Derived extends Base {

    static
    {
        Base.myVar = 10;
    }
}

Ma fonction main est comme ceci:

public static void main(String[] args)  {
    System.out.println(Derived.myVar);
    System.out.println(Base.myVar);
}

Ceci affiche la sortie sous la forme 0 0 où, comme prévu, 10 0. Quelqu'un peut-il expliquer ce comportement? De plus, si je veux que mes classes dérivées définissent les valeurs d'une variable statique, comment puis-je y parvenir?

30
Asha

Tel que je le comprend. Vous n'appelez pas de propriétés Derived (myVar appartient à Base et non à Derived). Et Java n’exécute pas le bloc statique de Derived. Si vous ajoutez un champ statique à Derived et y accédez, Java exécute tous les blocs statiques.

class Base {

    static public int myVar;

}


class Derived extends Base {

    static public int myVar2;

    static
    {
        Base.myVar = 10;
    }
}


public class Main {
    public static void main( String[] args ) throws Exception {
        System.out.println(Derived.myVar2);
        System.out.println(Base.myVar);
    }
}

A partir de la spécification Java, lorsque la classe est initialisée (et que le bloc statique est exécuté):

12.4.1 En cas d'initialisation, une classe ou une interface de type T sera initialisée immédiatement avant la première occurrence de l'un des événements suivants:

• T est une classe et une instance de T est créée.
• T est une classe et une méthode statique déclarée par T est invoquée.
• Un champ statique déclaré par T est attribué.
• Un champ statique déclaré par T est utilisé et le champ n'est pas une variable constante (§4.12.4).
• T est une classe de niveau supérieur (§7.6), et une instruction d'assertion (§14.10) imbriquée lexicalement dans T (§8.1.3) est exécutée.

22

Les blocs d’initialisation statiques ne sont exécutés que lorsque la classe est initialisée. Voir Spécification du langage Java paragraphes 8.7 (Initialiseurs statiques) et 12.4.1 (Lorsque l'initialisation se produit):

Un initialiseur statique déclaré dans une classe est exécuté lors de l'initialisation de la classe (§12.4.2). Les initialiseurs statiques peuvent être utilisés pour initialiser les variables de classe de la classe, en association avec tout initialiseur de champ pour les variables de classe (§8.3.2).

Voici un exemple similaire tout droit sorti de JLS 12.4.1:

class Super {
  static int taxi = 1729;
}
class Sub extends Super {
  static { System.out.print("Sub "); }
}
class Test {
  public static void main(String[] args) {
    System.out.println(Sub.taxi);
  }
}

Ce programme n'imprime que:

1729

parce que la classe Sub n'est jamais initialisée; la référence à Sub.taxi est une référence à un champ effectivement déclaré dans la classe Super et ne déclenche pas l'initialisation de la classe Sub.

6
esaj

Il existe une copie unique de myVar et les classes parent et enfant partagent la même chose. Jusqu'à ce que la classe enfant soit initiée.

1
BOSS

Quand on fait

class Base {

    public static int myVar = 0;
    static {
        System.out.println("Base");
    }
}

class Derived extends Base {

    static {
        System.out.println("Derived");
        Base.myVar = 9;

    }
}

public class StaticBlock {

    public static void main(String[] args) {

        System.out.println(Base.myVar);
        System.out.println(Derived.myVar);
    }
}

La sortie sera Base 0 0

Cela signifie que le bloc statique de la classe dérivée ne s'exécute pas .. !!

0
januprasad

Voici le lien vers la spécification Java - la section 8.7 parle d’initialiseurs statiques. Il donne de bons détails sur la façon dont ils devraient fonctionner et l'ordre dans lequel ils sont appelés. http://docs.Oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.7

0
Johnnie