java - Java ClassLoader 是否加载内部类?

标签 java classloader

如果我有一个内部类声明,例如:

Class A {
    public static class B {
    }
}

接着是:

Class<?> implClass = getClass().getClassLoader().loadClass("A");

A$B 内部类也会被加载吗? 如果 B 内部类没有声明为“静态”呢?

最佳答案

一旦代码被编译,就没有内部类这种东西了。如果你查看 javac 的结果,你会看到两个文件:

A.class
A$B.class

所以类BA被加载的时候并没有被加载,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;
        }
    }
    

注意

  1. A$B 没有对其父级 A 的引用,而 A$C 有。这是因为前者是静态内部类,而后者不是,并且
  2. A$BA$C 现在都是 package private 类。

这就是非静态内部类能够直接引用其父实例的字段和方法的方式,反之亦然。 (内部类中引用的父类的任何私有(private)字段也被设为包私有(private)。)

接下来我们看看加载类AA$BA$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 - Get a list of all Classes loaded in the JVM)。

在命令行运行gradle run(运行Mainmain方法);输出(带有我添加的注释)是

: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.Mainkuporific.A 的加载时间,但我们看不到 kuporific.A$Bkuporific.A$C 正在加载中。

关于java - Java ClassLoader 是否加载内部类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24538509/

相关文章:

java - 为什么这个类可以被Java类加载器加载两次?

java - "__JVM_DefineClass__"作为类加载器位置意味着什么?

java - 为什么 Log4J2 查找文件名中带有类加载器字符串的配置文件?

java - Postgres 中的 Bad Integer 2147483649(其 BIGINT 值)错误

osgi - 如何从 OSGi Bundle 中使用 Java 扩展执行 XSLT 转换

Java 安全 : Sandboxing plugins loaded via URLClassLoader

java - 在Android上将视频分成几部分

java - JSF 2.0 ValueExpression 中的可用运算符

java - Vavr 中列表上的模式匹配对象分解

java - Swing - UI 重新验证未发生