Question

J'arrive à venir à travers un code Java à mon lieu de travail. Voici le scénario:. Il y a 2 classes - ClassA et ClassB

ClassA n'a rien, sauf 4 valeurs de chaîne finale statiques publics à l'intérieur. Son but est d'utiliser ces valeurs comme ClassA.variable (ne me demandez pas pourquoi, ce n'est pas mon code).

importations de ClassB ClassA. Je modifié les valeurs de chaîne dans ClassA et compilé. Quand je courais ClassB je pouvais voir qu'il utilisait les anciennes valeurs - non pas les nouvelles valeurs. Je devais recompiler ClassB pour le faire utiliser de nouvelles valeurs de ClassA! (Je devais recompiler les autres classes que les importations ClassA!)

Est-ce seulement à cause de JDK 1.6 ou je aurais dû savoir plus tôt recompiler ClassB aussi! Éclaire-moi. :)

Était-ce utile?

La solution

Si les valeurs des variables final de la classe ClassA se trouvent des constantes de compilation, le compilateur aurait pu les inline dans les classes à l'aide ClassA au lieu de générer une référence d'exécution. Je pense que, ce qui est arrivé dans le cas que vous avez décrit.

Exemple:

public class Flags {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

public class Consumer {
    public static void main(String[] args) {
         System.out.println(Flags.FOO);
    }
}

Dans cet exemple, le compilateur sera probablement intégrer la valeur de FOO dans le code généré pour Consumer au lieu de générer la référence d'exécution équivalent. Si la valeur des changements de FOO plus tard, vous devrez recompiler Consumer afin d'avoir utiliser la nouvelle valeur.

Ceci est une optimisation, qui a quelques avantages par rapport à l'efficacité et la rapidité du programme compilé. Par exemple, la valeur inline pourrait permettre de nouvelles optimisations dans les expressions qui utilisent, par exemple:

int x = Flags.FOO * 10;

Dans cet exemple, la valeur inline (ici: 1). Permet au compilateur de remarquer que la multiplication ne fait aucune différence, et peut être omis alltogether

Autres conseils

Il est un problème de compatibilité binaire. Les références à des champs constants sont résolus au moment de la compilation. Le comportement que vous voyez est correct; si vous modifiez les valeurs de la classe A, alors vous devrez recompiler le client (classe B). Pour éviter de tels problèmes envisager d'ajouter des constantes en utilisant un type ENUM, introduit en Java version 5.0.

Pourquoi vous essayez de compiler les classes individuellement?

Utilisez un système de construction comme Maven ou fourmi ou tout simplement laisser votre IDE le faire.

La seule chose sûre à faire est de recompiler chaque java qui dépend d'une classe java qui a changé jusqu'à ce que toutes les classes qui pourraient être effectuées a été recompilé.

Si vous n'utilisez pas les valeurs dans un commutateur, vous pouvez le faire à la place:

public class A
{
    public static final int FOO;
    public static final String BAR;

    static
    {
        FOO = 42;
        BAR = "Hello, World!";
    }
}

le compilateur ne sera plus coder en dur les valeurs dans les autres classes qui les utilisent.

Supposons ClassA ressemble à ceci:

public class ClassA {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

Si vous recompiler, ClassB va continuer à utiliser les anciennes valeurs. Je suppose que cela pourrait dépendre du compilateur, mais je pense que c'est le comportement typique. Si vous ne voulez pas recompiler ClassB à chaque fois une constante dans les changements ClassA, vous devez faire quelque chose comme ceci:

public class ClassA {
    public static final int FOO = CONST(1);
    public static final int BAR = CONST(2);

    public static int CONST(int i) { return i; }
}

Becuase maintenant javac ne veut pas inline les constantes. Au contraire, il appellera la méthode CONST (int) lorsque initialiseur statique ClassA fonctionne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top