Jeśli jeden zapisuje dwie publiczne klasy Java z tą samą nazwą niewrażliwą na wielkość liter w różnych katalogach, wówczas obie klasy nie są użyteczne w środowisku wykonawczym. (Testowałem to w systemach Windows, Mac i Linux z kilkoma wersjami JVM HotSpot. Nie zdziwiłbym się, gdyby inne JVM-y, w których byłyby jednocześnie użyteczne.) Na przykład, jeśli utworzę klasę o nazwie a
i jedną o nazwie A
, tak jak to :Rozróżnianie wielkości liter w nazwach klas 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";
}
}
Trzy projekty Eclipse zawierające kod powyżej są available from my website.
Jeśli spróbować ja nazywając myCase
na obu klasach tak:
System.out.println(A.myCase());
System.out.println(a.myCase());
typechecker powiedzie, ale kiedy uruchomić plik klasy generowania przez kod bezpośrednio powyżej uzyskać:
Exception in thread "main" java.lang.NoClassDefFoundError: testcase/A (wrong name: testcase/a)
W Java, nazwy są w dużym stopniu wrażliwe. Niektóre systemy plików (na przykład Windows) nie są rozróżniane wielkości liter, więc nie jestem zaskoczony powyższym zachowaniem, ale wygląda na to, że jest nieprawidłowy. Niestety specyfikacje Java są dziwnie nieprecyzyjne, a jakie klasy są widoczne. Java Language Specification (JLS), Java SE 7 Edition (rozdział 6.6.1, strona 166) mówi:
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.
w punkcie 7.3, JLS definiuje obserwowanie jednostce kompilacji pod względem wyjątkowo niejasne:
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.
Java Virtual Machine Specification jest podobnie niejasne (sekcja 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.
Wszystko to prowadzi do czterech pytań w porządku malejącym znaczeniu:
- Czy są jakieś gwarancje dotyczące klas ładowanych przez domyślny moduł ładujący klasy w każdej maszynie JVM? Innymi słowy, czy mogę zaimplementować poprawną, ale zdegenerowaną maszynę JVM, która nie załaduje żadnych klas, z wyjątkiem tych w java.lang i java.io?
- Jeśli są jakieś gwarancje, czy zachowanie w powyższym przykładzie narusza gwarancję (tj. Czy zachowanie jest błędem)?
- Czy istnieje sposób na jednoczesne ładowanie HotSpot
a
iA
? Czy pisanie niestandardowego programu ładującego klasy?
Więc niech mi to wprost .. Masz dwie klas o podobnych nazwach 'testcase.a' i' testcase.A ', w dwóch * różnych * katalogach na ścieżce klas (ponieważ nie możesz mieć ich w tym samym katalogu w systemie plików niewrażliwym na wielkość liter) - i zastanawiasz się, dlaczego JVM nie może znaleźć odpowiedniego pliku klasy do załadowania? –
@GregHewgill Opisałeś scenariusz na początku mojego pytania poprawnie, ale moje pytania są szersze. –
Cóż, cały pomysł "ścieżki klasy" jest zależny od platformy z punktu widzenia JLS i JVMS. Żaden z tych dokumentów nie pomoże ci rozwiązać tego problemu. –