Ответ 1
После компиляции кода нет такой вещи, как внутренний класс. Если вы посмотрите на результаты javac
, вы увидите два файла:
A.class
A$B.class
Таким образом, класс B
не загружается, когда загружается A
, B
просто определяется как A
.
Изменить
Например, учитывая эти два файла,
package kuporific;
public class A {
private static class B {}
private class C {}
}
и build.gradle
(для удобства):
apply plugin: 'java'
Сначала создайте, запустив gradle build
. Затем распакуйте полученный JAR файл (расположенный в build/libs
):
├── META-INF
│ └── MANIFEST.MF
└── kuporific
├── A$B.class
├── A$C.class
└── A.class
Открытие каждого файла (например, в IntelliJ) показывает, что сделал компилятор:
-
A.class
:package kuporific; public class A { public A() { } private class C { public C() { } } private static class B { public B() { } } }
-
A$B.class
:package kuporific; class A$B { private A$B() { } }
-
A$C.class
:package kuporific; import kuporific.A; class A$C { private A$C(A this$0) { this.this$0 = this$0; } }
Обратите внимание, что
-
A$B
не имеет ссылки на его родителя,A
, аA$C
. Это связано с тем, что первый является статическим внутренним классом, а последний - нет, а - оба
A$B
иA$C
теперь являются частными классами пакетов.
Таким образом, нестатические внутренние классы могут напрямую ссылаться на свои родительские экземпляры полей и методов и наоборот. (Любые частные поля родительского класса, упомянутые во внутреннем классе, также становятся закрытыми для пакета.)
Далее, посмотрим, какой эффект загружает класс A
на A$B
и A$C
.
Сначала добавьте следующий класс Java:
package kuporific;
public class Main {
public static void main(String[] args) throws ClassNotFoundException {
Main.class.getClassLoader().loadClass("kuporific.A");
}
}
Теперь добавьте следующее в файл build.gradle
:
apply plugin: 'application'
mainClassName = 'kuporific.Main'
applicationDefaultJvmArgs = ["-verbose:class"]
-verbose:class
выводит все классы, загружаемые JVM (см. Java - получить список всех классов, загруженных в JVM).
Запустите gradle run
в командной строке (который запускает метод main
main
); вывод (с моими добавленными примечаниями)
:compileJava
:processResources UP-TO-DATE
:classes
:run
[Opened /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Object from /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
# Lots of omitted output...
[Loaded kuporific.Main from file:/tmp/build/classes/main/]
^ here!
[Loaded sun.launcher.LauncherHelper$FXHelper from /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Class$MethodArray from /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded kuporific.A from file:/tmp/build/classes/main/]
^ here!
[Loaded java.lang.Shutdown from /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
[Loaded java.lang.Shutdown$Lock from /Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home/jre/lib/rt.jar]
BUILD SUCCESSFUL
Total time: 6.502 secs
Мы можем видеть, когда были загружены kuporific.Main
и kuporific.A
, и мы не видим загрузки kuporific.A$B
или kuporific.A$C
.