Groß- und Kleinschreibung von Java-Klassennamen

Wenn man zwei öffentliche Java-Klassen mit dem gleichen Namen ohne Berücksichtigung der Groß- und Kleinschreibung in verschiedene Verzeichnisse schreibt, können beide Klassen zur Laufzeit nicht verwendet werden. (Ich habe dies unter Windows, Mac und Linux mit verschiedenen Versionen der HotSpot-JVM getestet. Es würde mich nicht wundern, wenn es andere JVMs gibt, in denen sie gleichzeitig verwendet werden können.) Zum Beispiel, wenn ich eine Klasse namens erstellea und einer namensA wie so:

// 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";
    }
}

Drei Eclipse-Projekte, die den obigen Code enthalten, sind:verfügbar von meiner Website.

Wenn ich es versuche, rufe ich anmyCase in beiden Klassen wie folgt:

System.out.println(A.myCase());
System.out.println(a.myCase());

Der Typchecker ist erfolgreich, aber wenn ich die Klassendatei starte, die durch den Code direkt darüber generiert wird, erhalte ich:

Ausnahme im Thread "main" java.lang.NoClassDefFoundError: testcase / A (falscher Name: testcase / a)

In Java wird bei Namen im Allgemeinen zwischen Groß- und Kleinschreibung unterschieden. Bei einigen Dateisystemen (z. B. Windows) wird die Groß- und Kleinschreibung nicht berücksichtigt. Daher wundert es mich nicht, dass das oben beschriebene Verhalten auftritt, aber es scheintfalsch. Leider sind die Java-Spezifikationen seltsamerweise nicht verbindlich, welche Klassen sichtbar sind. DasJava Language Specification (JLS), Java SE 7 Edition (Abschnitt 6.6.1, Seite 166) lautet:

Wenn eine Klasse oder ein Schnittstellentyp als öffentlich deklariert ist, kann mit jedem Code auf sie zugegriffen werden, vorausgesetzt, die Kompilierungseinheit (§7.3), in der sie deklariert ist, ist beobachtbar.

In Abschnitt 7.3 definiert das JLS die Beobachtbarkeit einer Kompilierungseinheit in äußerst vagen Begriffen:

Alle Kompilierungseinheiten des vordefinierten Pakets Java und seiner Unterpakete lang und io sind immer beobachtbar. Für alle anderen PaketeDas Host-System bestimmt, welche Kompilierungseinheiten beobachtbar sind.

DasJava Virtual Machine-Spezifikation ist ähnlich vage (Abschnitt 5.3.1):

Die folgenden Schritte werden verwendet, um die mit [Binärname] N bezeichnete Nonarray-Klasse oder Schnittstelle C mit dem Bootstrap-Klassenladeprogramm [...] zu laden und dadurch zu erstellen. Andernfalls übergibt die Java Virtual Machine das Argument N an einen Aufruf einer Methode weiter Das Bootstrap-Klassenladeprogramm, um plattformabhängig nach einer angeblichen Darstellung von C zu suchen.

All dies führt zu vier Fragen in absteigender Reihenfolge der Wichtigkeit:

Gibt es Garantien dafür, welche Klassen von den Standardklassenladeprogrammen in jeder JVM geladen werden können? Mit anderen Worten, kann ich eine gültige, aber entartete JVM implementieren, die keine Klassen außer den Klassen in java.lang und java.io lädt?Wenn es Garantien gibt, verstößt das Verhalten im obigen Beispiel gegen die Garantie (d. H. Ist das Verhalten ein Fehler)?Gibt es eine Möglichkeit, HotSpot zu ladena undA gleichzeitig? Würde das Schreiben eines benutzerdefinierten Klassenladeprogramms funktionieren?

Antworten auf die Frage(3)

Ihre Antwort auf die Frage