Java ClassLoader 是否装入内部类?
2022-09-01 17:22:01
如果我有一个内部类声明,例如:
Class A {
public static class B {
}
}
其次:
Class<?> implClass = getClass().getClassLoader().loadClass("A");
A$B 内部类是否也会被加载?如果 B 内部类未声明为“静态”,该怎么办?
如果我有一个内部类声明,例如:
Class A {
public static class B {
}
}
其次:
Class<?> implClass = getClass().getClassLoader().loadClass("A");
A$B 内部类是否也会被加载?如果 B 内部类未声明为“静态”,该怎么办?
一旦代码被编译,就没有内部类这样的东西了。如果您查看 的结果,您将看到两个文件: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'
首先,通过运行来构建。然后,解压缩生成的 JAR 文件(位于):gradle build
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"]
输出由 JVM 加载的所有类(请参阅 Java - 获取 JVM 中加载的所有类的列表)。-verbose:class
在命令行上运行(运行 );输出(带有我添加的注释)是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
内部类即不能存在于父类之外。您需要首先构造父类。class B
class A
如果你从你的内部类中删除静态,即非静态内部类,你需要在构造内部类时传递父类。
Object a = Class.forName("A").newInstance(); //object of outer class
//object of inner class
Object b = implClass.getDeclaredConstructor(new Class[] { a.getClass() })
.newInstance(new Object[] { a });