【问题标题】:Java: How to load a class (and its inner classes) that is already on the class path?Java:如何加载已经在类路径上的类(及其内部类)?
【发布时间】:2010-05-19 18:40:35
【问题描述】:

如何加载已经在类路径上的类、实例化它以及实例化其中定义的任何内部类?

EG:

public class TestClass {


    public class InnerClass { }

}

【问题讨论】:

  • 实际上,只需执行new TestClass(); 即可加载您的类(如果尚未加载)并实例化它。 new TestClass().new innerClass(); 也一样。

标签: java reflection classloader


【解决方案1】:

内部类不能存在于父类之外。您需要先构造父类。没有反射,这看起来像:

InnerClass innerClass = new TestClass().new InnerClass();

在反射中,需要在构造内部类时传入父类。

Object testClass = Class.forName("com.example.TestClass").newInstance();
for (Class<?> cls : testClass.getClass().getDeclaredClasses()) {
    // You would like to exclude static nested classes 
    // since they require another approach.
    if (!Modifier.isStatic(cls.getModifiers())) {
        Object innerClass = cls
            .getDeclaredConstructor(new Class[] { testClass.getClass() })
            .newInstance(new Object[] { testClass });
    }
}

【讨论】:

  • @BalusC,为什么说没有父类就不能存在内部类,我们需要先构造父类?即使我们不能在不加载外部类的情况下实例化内部类,但我们绝对可以在加载父类之前加载(构造一个Class实例)内部类:stackoverflow.com/questions/25458617/…Class.forName("Outer$Inner");不会隐式加载Class.forName("Outer");
  • @Pacerier:您将嵌套类与内部类混淆了。您所指的答案涉及(静态)嵌套类。回到书本:docs.oracle.com/javase/tutorial/java/javaOO/nested.html
  • @BalusC,我没有,我给你的链接是评论链接,而不是答案。请允许我重复一遍:我们绝对可以在加载外部类之前加载内部类(我不是在谈论嵌套类)。使用-verbose 标志自己测试它:Class.forName("Outer$Inner"); 加载内部类而不加载外部类。事实上,我们甚至可以做到Class.forName("Outer$Inner").getMethod("M1");,而无需加载外部类。
【解决方案2】:

作为旁注,鉴于您的主要问题已得到解答 - 人们通常会像上面的示例中那样声明内部类,而不考虑它们是否可以是 static 内部类。

根据我的经验,绝大多数(非匿名)内部类可以是静态的,因为它们不需要访问其父类的实例成员。在这种情况下将内部类声明为静态既更有效(因为运行时不需要为每个父实例定义一个新类),更少混淆(因为new TestClass().new InnerClass().getClass() != new TestClass().new InnerClass().getClass())并且如果你没有更容易实例化一个适当的TestClass 实例。

因此,如果这适用于您,您可以(并且可以说应该)这样声明您的内部类:

public class TestClass {

    public static class InnerClass { }

}

然后您可以简单地将其实例化为new TestClass.InnerClass()

(如果您需要从 InnerClass 中访问成员字段,那么当然忽略所有这些!)

【讨论】:

  • 是的,就像final 变量一样,可以说它应该是语言级别的默认值 - 因此需要将其设为习惯级别的默认值。
  • 我同意。但是话又说回来,大多数在某些时候体验过函数式编程语言的人也是如此。
  • 运行时不需要“为每个父实例定义一个新类”。内部类只有一个定义(字节码),即使它不是静态的。内部类和嵌套类(即带有static 的类)之间的一个主要区别是编译器在内部类中自动生成的父类引用变量的隐式定义。我同意你关于优先嵌套类而不是内部类的观点。
【解决方案3】:
Class.forName("your classname").newInstance().

只有在构造函数实例化内部类时才会实例化它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-09-14
    • 2020-10-11
    • 2021-04-21
    • 2011-01-26
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多