Si on écrit deux classes Java avec la même casse nom dans des répertoires différents, puis les deux classes ne sont pas utilisables au moment de l'exécution. (J'ai testé sur Windows, Mac et Linux avec plusieurs versions de la JVM HotSpot. Je ne serais pas surpris si d'autres machines virtuelles où ils sont utilisables simultanément.) Par exemple, si je crée une classe nommée a
et un nommé A
comme:
// lowercase/src/testcase/a.java
package testcase;
public class a {
public static String myCase() {
return "lower";
}
}
// uppercase/src/testcase/A.java
package testcase;
public class A {
public static String myCase() {
return "upper";
}
}
Trois projets eclipse contenant le code ci-dessus sont disponibles à partir de mon site web.
Si vous essayez ce que j'appelle myCase
sur les deux classes comme suit:
System.out.println(A.myCase());
System.out.println(a.myCase());
Le typechecker réussit, mais quand je lance le fichier de classe générer par le code directement au-dessus, j'obtiens:
Exception in thread "main" java.lang.NoClassDefFoundError: cas de test/Un (mauvais nom: testcase/a)
En Java, les noms sont en général sensibles à la casse. Certains systèmes de fichiers (par exemple Windows) sont insensibles à la casse, donc je ne suis pas surpris de ce comportement se produit, mais il semble mauvais. Malheureusement, les spécifications Java bizarrement non-commital sur les classes qui sont visibles. Le Langage Java Specification (JLS), Java SE 7 Édition (Section 6.6.1, page 166) dit:
Si une classe ou une interface de type est déclaré en public, alors il peut être consulté par tout code, à condition que l'unité de compilation (§7.3) dans lequel elle est déclarée est observables.
Dans la Section 7.3, la JLS définit l'observabilité d'une unité de compilation extrêmement vague:
Toutes les unités de compilation de la prédéfinis package java et de ses sous-lang et io sont toujours observables. Pour tous les autres paquets, le système hôte détermine les unités de compilation sont observables.
La Machine Virtuelle Java de Spécification est de la même manière vague (Section 5.3.1):
Les étapes suivantes sont utilisées pour charger et de créer ainsi la nonarray classe ou interface C notée par [nom binaire] N à l'aide de la classe de bootstrap loader [...] Sinon, la machine virtuelle Java passe l'argument N à un appel d'un méthode de la classe de bootstrap loader à la recherche d'une prétendue représentation de C dans une plate-forme de manière dépendante.
Tout cela conduit à quatre questions dans l'ordre décroissant d'importance:
- Sont-il des garanties sur les classes qui sont chargeables par la valeur par défaut de la classe loader(s) dans chaque JVM? En d'autres termes, puis-je mettre en œuvre un valide, mais dégénérée de la JVM, qui ne se charge pas toutes les classes à l'exception de ceux de java.lang et de java.io?
- S'il y a des garanties, le comportement dans l'exemple ci-dessus violent la garantie (c'est à dire le comportement d'un bug)?
- Est-il possible de faire un HotSpot de la charge
a
etA
simultanément? Aurait écrit une classe personnalisée chargeur de travail?