2010-03-23 8 views
1

Extrait de code java simple. Il a trois classes. Après avoir compilé le code, supprimez A.class, puis exécutez le code. Le code fonctionne toujours, pourquoi ne vérifie pas si le code d'octet de A existe ou non?Comportement du compilateur Tricky

class A { 
    static { 
     System.out.println("In the class A"); 
    } 

    public A() { 
    } 
} 

class B { 
    private A a = null; 

    static { 
     System.out.println("In the class B"); 
    } 

    public B() { 
     a = new A(); 
    } 
} 

public class ExampleLinkage { 
    static { 
     System.out.println("In the class A"); 
    } 

    public ExampleLinkage(String str) { 
    } 

    public static void main(String args[]) { 
     try { 
      System.out.println("In the main method of ExampleLinkage"); 
      Class.forName("com.bt.rtti.B"); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Notez que rien ne décrit ici le comportement délicat du compilateur. Vous ne comprenez pas –

+0

Son discutable.Mais je ne suis pas sûr du comportement correct du compilateur.Il pourrait être le cas de faire une certaine optimisation et ne pas ajouter le code d'octet pertinent de classe A. – Neeraj

+0

Non, le compilateur Java généralement ne fait quasiment pas d'optimisations et je suis à peu près sûr qu'il ne fait pas celui-là (d'autant qu'il ne serait pas valide de toute façon)). Vous pouvez facilement réfuter cette hypothèse en décompilant 'B.class' avec javap:' javap -v B' –

Répondre

5

Je suppose que la classe A ne doit à aucun moment être chargée, même s'il existe une instance dans B, puisque vous n'instanciez jamais une instance de B.

la JVM est très paresseuse lorsqu'elle charge des classes . il les charge soit lorsque vous instanciez un objet de cette classe (à la première fois), quand vous chargez explicitement une classe avec Class.forName() ou lorsque vous référencez la classe d'une manière qui nécessite des informations de celle-ci (essayez d'accéder à un membre statique de A à partir de l'initialiseur statique de B et voir que A sera chargé

1

Comme vous ne le recompilez pas, exécutez simplement la classe.

+0

Je ne comprends pas cette réponse. La recompilation nécessiterait le fichier .java, pas le fichier .class. –

+0

Juste pour faire le point que le JRE ne vérifie pas si des classes compliées existent, seul le compilateur cherche des fichiers sources ou des classes conformes dans le chemin de la classe. – Gordon

0

La classe A n'est pas utilisée dans le code (c'est-à-dire dans la méthode principale).

Lors de l'exécution, les classes d'exécution sont chargées. À ce moment-là, vous obtiendriez une erreur ClassNotFoundError. Mais si vous n'utilisez pas la classe, il n'y a pas besoin d'être là. Essayez de créer une instance de B (qui a besoin d'une instance de A), vous obtiendrez alors une erreur.

0

Suite à la réponse de Gordon, vous ne en cours d'exécution de la classe et la classe A n'est pas nécessaire, si vous avez appelé le constructeur de A ou fait référence à un champ ou une méthode statique dans A, alors vous obtenir le ClassNotFoundException vous attendez