当前位置: 首页 > 知识库问答 >
问题:

Java类加载器是否加载内部类?

梁渊
2023-03-14

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

Class A {
    public static class B {
    }
}

其次是:

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

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

共有3个答案

归明诚
2023-03-14

一个ClassLoader将不会加载一个类,除非它被请求(例如使用loadClass)。加载类时,ClassLoader将请求引用的类。

由于您的类A没有引用A.BA.B将不会被加载,无论它是否是静态的。(老实说,A确实引用了A.B,但不会导致ClassLoader加载A.B

如果您添加类型为a.B的字段,或以另一种方式使用类型a.B(例如,作为方法返回类型),它实际上将在a.class中引用,因此将被加载。

邹曦之
2023-03-14

内部类,即类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 });
宿淳
2023-03-14

一旦代码被编译,就没有所谓的内部类了。如果您查看javac的结果,您将看到两个文件:

A.class
A$B.class

因此,当加载A时,类B不会加载,B恰好是在A定义的。

例如,给定这两个文件,

package kuporific;

public class A {
    private static class B {}
    private class C {}
}

和一个build.gradle文件(为了方便):

apply plugin: 'java'

首先,通过运行gradlebuild进行构建。然后,解压缩生成的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有。这是因为前者是一个静态的内部类,而后者不是,并且

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

    接下来,让我们看看加载类AA$BA$C有什么影响。

    首先,添加以下Java类:

    package kuporific;
    
    public class Main {
        public static void main(String[] args) throws ClassNotFoundException {
            Main.class.getClassLoader().loadClass("kuporific.A");
        }
    }
    

    现在将以下内容添加到构建中。渐变文件:

    apply plugin: 'application'
    mainClassName = 'kuporific.Main'
    applicationDefaultJvmArgs = ["-verbose:class"]
    

    -verbose:class输出JVM加载的所有类(请参阅Java-获取JVM中加载的所有类的列表)。

    在命令行上运行gradlerun(运行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
    

    我们可以看到当kuporify。主代码和代码。加载了一个,我们没有看到两个kuporify。A$Bkuporify。正在加载$C

  •  类似资料:
    • 问题内容: 如果我有一个内部类声明,例如: 其次是: A $ B内部类也将被加载吗?如果B内部类未声明为“静态”怎么办? 问题答案: 一旦代码被编译, 就没有内部类之类的东西 。如果查看的结果,则会看到两个文件: 因此,类在加载时不会加载,只是 碰巧 在中定义了。 编辑 例如,鉴于这两个文件, 和一个文件(为方便起见): 首先,通过运行进行构建。然后,解压缩生成的JAR文件(位于中): 打开每个文

    • CLMAIN->clA(类A,$B)。$B是类a的内部类B。 从clMain创建具有指定url的新clA到包含类A(和类$B)的jar文件。然后通过CLA创建新对象A。 从X加载的另一个类通过接口执行对象a的方法没有问题。 然后,在该方法中,应该创建新对象$b,但它抛出. 在类A的构造函数中加载类$B可以解决以下问题:

    • 问题内容: 我们知道我们可以使用以下方法覆盖System 类加载器: 那么,既然它本身是一个类,它是由谁加载的? 我们如何获得该“元”类加载器的类文件? 问题答案: 从Javadoc中获取: 如果在首次调用此方法时定义了系统属性“ java.system.class.loader”,则该属性的值将作为要作为系统类加载器返回的类的名称。 该类使用默认的系统类加载器加载, 并且必须定义一个公共构造函数

    • 因此,我有一个类加载器加载一个类,如下所示: 类在运行时位于另一个jar中。以及是在主jar中生成的,然后我取消了它的归档,所以依赖项就在那里。 如何从外部访问其他依赖项。我加载的类文件? 例外情况:

    • 框架中所有的类都是通过类加载器(ClassLoader)加载的,通过Loader我们可以实现类的统一管理。下面我们一起来看看Loader提供了哪些加载方法: 1. Loader::import 加载一个类或者加载一个包 方法原型 import( $classPath, $type = IMPORT_APP, $extension=EXT_PHP ) 参数名称 参数说明 $classPath 文件的

    • 加载器,顾名思义,是用于加载元素的,加载的元素可以是库(类),视图文件 , 驱动器 ,辅助函数 , 模型 或其他你自己的文件。 注解 该类由系统自动加载,你无需手工加载。 应用程序"包" 包的视图文件 类参考 应用程序"包" 应用程序包(Package)可以很便捷的将你的应用部署在一个独立的目录中, 以实现自己整套的类库,模型,辅助函数,配置,文件和语言包。 建议将这些应用程序包放置在 appli