dernière variable statique publique dans une classe java importés
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. :)
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.