Si se escriben dos clases Java públicas con el mismo nombre insensible a mayúsculas y minúsculas en directorios diferentes, ambas clases no se pueden usar en el tiempo de ejecución. (Probé esto en Windows, Mac y Linux con varias versiones de HotSpot JVM. No me sorprendería que haya otras JVM donde se puedan usar simultáneamente.) Por ejemplo, si creo una clase llamada a
y una llamada A
como tal :Sensibilidad de mayúsculas y minúsculas de los nombres de clases Java
// 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";
}
}
Tres proyectos de Eclipse que contienen el código anterior son available from my website.
Si trato que llamar myCase
en ambas clases de este modo:
System.out.println(A.myCase());
System.out.println(a.myCase());
El typechecker tiene éxito, pero cuando ejecuto el archivo de clase generar por el código directamente encima me sale:
Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)
En Java, los nombres son en general sensibles a mayúsculas y minúsculas. Algunos sistemas de archivos (por ejemplo, Windows) no distinguen entre mayúsculas y minúsculas, por lo que no me sorprende que ocurra el comportamiento anterior, pero parece que es incorrecto. Lamentablemente, las especificaciones de Java son extrañamente inexistentes sobre qué clases son visibles. El Java Language Specification (JLS), Java SE 7 Edition (Sección 6.6.1, página 166) dice:
If a class or interface type is declared public, then it may be accessed by any code, provided that the compilation unit (§7.3) in which it is declared is observable.
En la sección 7.3, el JLS define observabilidad de una unidad de compilación en términos muy vagos:
All the compilation units of the predefined package java and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable.
la Java Virtual Machine Specification es igualmente vaga (sección 5.3.1):
The following steps are used to load and thereby create the nonarray class or interface C denoted by [binary name] N using the bootstrap class loader [...] Otherwise, the Java virtual machine passes the argument N to an invocation of a method on the bootstrap class loader to search for a purported representation of C in a platform-dependent manner.
Todo esto conduce a cuatro preguntas en orden descendente de importancia:
- ¿Hay alguna garantía sobre qué clases pueden cargar los cargadores de clases predeterminados en cada JVM? En otras palabras, ¿puedo implementar una JVM válida pero degenerada que no cargue ninguna clase excepto las de java.lang y java.io?
- Si hay alguna garantía, ¿el comportamiento en el ejemplo anterior infringe la garantía (es decir, el comportamiento es un error)?
- ¿Hay alguna manera de hacer que HotSpot cargue
a
yA
simultáneamente? ¿Funcionaría la escritura de un cargador de clases personalizado?
Así que vamos a ver si lo entiendo .. tienes dos clases con nombres similares '' testcase.a' recta y testcase.A ', en dos * diferentes * directorios en su classpath (porque no puede tenerlos en el mismo directorio en un sistema de archivos insensible a mayúsculas y minúsculas) - y se pregunta por qué la JVM no puede encontrar el archivo de clase correcto para cargar? –
@GregHewgill Ha descrito correctamente el escenario al comienzo de mi pregunta, pero mis preguntas son más amplias. –
Bueno, la idea de un "classpath" depende de la plataforma desde el punto de vista de JLS y JVMS. Ninguno de esos documentos lo ayudará a resolver esta pregunta. –