Если вы пишете два открытых Java-класса с одним и тем же именем без учета регистра в разных каталогах, то оба класса не могут использоваться во время выполнения. (Я тестировал это на Windows, Mac и Linux с несколькими версиями JSM HotSpot.Я не удивлюсь, если есть другие JVM, где они могут использоваться одновременно.) Например, если я создам класс с именем a
и один с именем a
так:
// 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";
}
}
Три проекта eclipse, содержащие код выше, доступны с моего сайта.
Если попытаюсь позвонить myCase
в оба класса, например:
System.out.println(A.myCase());
System.out.println(a.myCase());
Ошибка typechecker, но когда я запускаю файл класса, генерируя код непосредственно выше, я получаю:
Исключение в потоке "main" java.lang.NoClassDefFoundError: testcase/A (неправильное имя: testcase/a)
В Java имена в общем случае чувствительны к регистру. Некоторые файловые системы (например, Windows) нечувствительны к регистру, поэтому я не удивлен, как это происходит, но это кажется неправильным. К сожалению, спецификации Java странно неконкретны, какие классы видны. Java Language Specification (JLS), Java SE 7 Edition (раздел 6.6.1, стр. 166) гласит:
Если класс или тип интерфейса объявлены общедоступными, к нему может быть любой код, при условии, что блок компиляции (§7.3), в котором он объявлен, является наблюдаемыми.
В разделе 7.3 JLS определяет наблюдаемость единицы компиляции в чрезвычайно неопределенных терминах:
Все единицы компиляции предопределенного пакета java и его подпакетов lang и io всегда наблюдаемы. Для всех других пакетов хост-система определяет, какие единицы компиляции наблюдаемы.
Спецификация виртуальной машины Java также смутно (раздел 5.3.1):
Следующие шаги используются для загрузки и тем самым создают класс nonarray или интерфейс C, обозначенный [binary name] N, с помощью загрузчика bootstrap class [...] В противном случае виртуальная машина Java передает аргумент N вызову метод загрузчика класса bootstrap для поиска предполагаемого представления C в зависимости от платформы.
Все это приводит к четырем вопросам в порядке убывания важности:
- Есть ли какие-либо гарантии относительно того, какие классы загружаются загрузчиком классов по умолчанию в каждой JVM? Другими словами, могу ли я реализовать действительный, но вырожденный JVM, который не будет загружать какие-либо классы, кроме тех, что указаны в java.lang и java.io?
- Если есть какие-либо гарантии, поведение в приведенном выше примере нарушает гарантию (т.е. является ли поведение ошибкой)?
- Есть ли способ сделать загрузку HotSpot
a
иa
одновременно? Будет ли писать пользовательский загрузчик классов?