使用反射实例化内部类时出现 InstantiationException。为什么?

2024-03-04

我无法创建 B 对象,但为什么呢?

public class AFactory {

    public int currentRange;

    private abstract class A {
        protected final Object range = currentRange;

        public int congreteRange = 28;
    }

    public class B extends A {
        public int congreteRange = 42;
    }

    synchronized A createNew(Class<? extends A> clazz) throws Exception {
        // EDIT: there is accessible default constructor
        currentRange = clazz.newInstance().congreteRange;
        return clazz.newInstance();
    }

    public static void main(String[] args) throws Exception {
        AFactory factory = new AFactory();
        System.out.println(factory.createNew(B.class).range);
    }
}

例外是:

Exception in thread "main" java.lang.InstantiationException: AFactory$B
at java.lang.Class.newInstance0(Class.java:357)
at java.lang.Class.newInstance(Class.java:325)
at AFactory.createNew(AFactory.java:15)
at AFactory.main(AFactory.java:21)

问题是你正在尝试实例化一个内部类,您只能在外部类的实例上访问它。内部类的构造函数采用隐式隐藏instance封闭类的。通过分析这个简单类的字节码就可以看到:

public class Demo {
    class Test {
    }
}

现在,编译代码:

javac Demo.java

这将创建两个类文件:

Demo.class
Demo$Test.class

运行以下命令查看字节码Demo$Test.class:

javap -c . Demo$Test

您将得到以下结果:

class Demo$Test {
  final Demo this$0;   

  Demo$Test(Demo);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1                  // Field this$0:LDemo;
       5: aload_0
       6: invokespecial #2                  // Method java/lang/Object."<init>":
()V
       9: return
}

那么,您看到该类的构造函数了吗?它需要Demo作为参数。因此,不存在 0-arg 构造函数。

但是,如果你让你的内部类static,它会起作用,因为这样您就不需要任何封闭类的实例来调用内部类构造函数。

With static内部类 - 替代方案:

public class AFactory {

    public static int currentRange;

    private static abstract class A {
        protected final Object range = AFactory.currentRange;
    }

    public static class B extends A {
        public int congreteRange = 42;
    }

    synchronized A createNew(Class<? extends B> clazz) throws Exception {
        currentRange = clazz.newInstance().congreteRange;
        return clazz.newInstance();
    }

    public static void main(String[] args) throws Exception {
        AFactory factory = new AFactory();
        System.out.println(factory.createNew(B.class).range);
    }
}

与非static内部类 - 最终代码:

如果你不想做它们static,那么您必须首先创建封闭类的实例。并将其传递给内部类的构造函数。要获取内部类的构造函数,可以使用Class#getDeclaredConstructor http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredConstructor%28java.lang.Class...%29 method.

现在,您必须修改工厂方法才能采取Constructor作为参数。像这样修改你的代码:

public class AFactory {

    public int currentRange;

    private abstract class A {
        protected final Object range = currentRange;
    }

    public class B extends A {
        public int congreteRange = 42;
    }

    synchronized A createNew(Constructor<? extends A> ctor) throws Exception {
        // Pass `this` as argument to constructor. 
        // `this` is reference to current enclosing instance
        return ctor.newInstance(this); 
    }

    public static void main(String[] args) throws Exception {
        AFactory factory = new AFactory();

        // Get constructor of the class with `AFactory` as parameter
        Class<B> bClazz = B.class;
        Constructor<B> ctor = bClazz.getDeclaredConstructor(AFactory.class);

        System.out.println(factory.createNew(ctor));
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用反射实例化内部类时出现 InstantiationException。为什么? 的相关文章

随机推荐

  • 如何在 Google 电子表格公式中将字符串转换为驼峰式

    尝试创建一个公式将由空格分隔的单词字符串转换为驼峰式 更小的版本 SUBSTITUTE PROPER TRIM A1 我们只需使用PROPER为大写和TRIM and SUBSTITUTE删除空格 如果我们想要小驼峰命名法 By just
  • 如何使用 JAVAFX 图表在图表上绘制多轴

    祝你平安 如何使用JavaFX图表API绘制多轴 以下是一个大型软件中的趋势图 其中绘制了一些实时数据和历史数据 注册了两支笔 每支笔的独立轴都在同一趋势上定义 我一直在尝试在 JavaFX 2 0 图表中做到这一点 我已经能够绘制实时图表
  • 如何在ggplot2中设置geom_smooth的se(置信区间)颜色? [复制]

    这个问题在这里已经有答案了 当我设置该功能时 geom smooth se TURE 置信区间是灰色的 但我想设置一些其他颜色 看起来是geom smooth中不能设置颜色的参数 我应该创建一个新的几何对象吗 或者有一些 ggplot2 扩
  • awk 脚本:如何防止 ARGV 被视为输入文件名

    看来 awk 脚本考虑了ARGV 1 to ARGV ARGC 作为输入文件 有没有办法让 awk 考虑到ARGV作为简单的参数而不是输入文件 Example test awk usr bin awk f BEGIN title ARGV
  • 如何在 MVC ScriptBundle 中将字符集设置为 .js 文件?

    我有 script js 文件 其中包含几个西里尔字母字符串 当我尝试使用像这样的标准链接加载它时 西里尔字母变成矩形 badCharsetCaracters 这解决了这个问题 如何使用 ASP NET MVC 4 Bundles 设置字符
  • 网站通过文档上传会暴露哪些安全漏洞?

    我是文档存储空间的新手 我还不确定我在做什么 但在开始之前我想知道当允许文档上传时可能存在的安全威胁以及清理数据的最佳方法是什么 我正在使用 PHP 并且允许使用图像 word 文档 pdf excel 文档等 这是一个好的解决方案吗 ht
  • Concourse 无法连接到 Docker 存储库

    我是广场新手 并尝试在我的环境中设置它 我在 Windows 机器上的 Virtualbox 6 1 4 r136177 上运行 Ubuntu 18 04 我设法让节点运行并设置大厅工作人员 并且我能够成功访问我的大厅仪表板 当我尝试运行本
  • QueryFailedError:格式错误的数组文字:typeORM 中的“[]”

    我正在尝试使用 TypeORM 在 postgres 中的表中添加新行 但收到 与数组文字相关的问题 问题发生在subscriptions field 实体格式 export class User PrimaryColumn userId
  • Hortonworks HDP Sandbox 上的 HBase:无法从 ZooKeeper 获取主地址

    我从 hortonworks for virtualbox 下载了 HDP 2 1 在简单命令中使用 Hbase shell 时出现以下错误 create t1 NAME gt f1 VERSIONS gt 5 Hortonworks 错误
  • CORS 请求在本地打开的 html 文件中被阻止

    我已经开始编写一个使用 JavaScript 显示数据的 HTML 文件 因为它应该尽可能简单地完成 所以我不想运行nodejs或任何其他本地http服务器 我刚刚在浏览器中打开了 HTML 文件 url 为 file home visu
  • 在rails中使用他的ip自动检测用户的时区

    我想从用户的 IP 地址找到他的时区 如果用户正在旅行 应用程序应该能够找出他所在的当前时区 你不能 至少可靠地 想想代理 ISP NAT 或 VPN 即使用户看起来在某个国家 地区 并不意味着他真的在那里 我建议让用户选择他喜欢的时区 并
  • .NET 中可以使用不可变数组吗?

    是否有可能以某种方式标记System Array作为不可变的 当放在 public get private set 后面时 它们无法添加到其中 因为它需要重新分配和重新分配 但消费者仍然可以设置他们希望的任何下标 public class
  • 跨服务器移动 mysql 文件

    我有一个巨大的 MySQL 数据库 大约 10 GB 我需要将其复制到不同的服务器 slicehost 我不想进行数据库转储并重新导入 b c 我认为这将花费很长时间 是否可以将原始 SQL 文件从一台机器移动到另一台机器 设置相同的 my
  • 当被模态视图控制器覆盖时,iOS 6 视图控制器布局在方向更改后不会更新

    我有一个 iPad 应用程序 非常适合 6 之前的 iOS 版本 我的根视图控制器显示一个列表 当您单击列表中的任何项目时 根视图控制器会呈现一个模式视图控制器来显示该项目的详细信息 问题是 我的根视图控制器在横向和纵向上有不同的布局 当不
  • Py_Initialize 运行需要哪些文件?

    我正在编写一段简单的代码 该代码从 C C 应用程序运行 Python 函数 为了做到这一点 我设置了 PYTHONPATH 并运行初始化 如下所示 Py SetPythonHome Python27 Py InitializeEx 0 然
  • 强制 R 不使用指数表示法(例如 e+10)?

    我可以强制 R 使用常规数字而不是使用e 10 类似符号 我有 1 810032e 09 and 4 在同一向量内并希望看到 1810032000 and 4 我正在为老式程序创建输出 我必须使用编写一个文本文件cat 到目前为止效果很好
  • java: Spring:如何将 bean 从一个 ClassPathXMLApplicationContext 传输到另一个?

    如何从一个豆子转移豆子ClassPathXMLApplicationContext到另一个 我创建一个这样的上下文 ClassPathXMLApplicationContext myOneContext new ClassPathXMLAp
  • 可展开列表视图自动折叠

    我无法在扩展新组时关闭之前扩展的组 我读过类似的问题 但我无法从中提取概念 我尝试使用 crashGroup groupPosition 方法 但它不起作用 您好 请尝试下面的代码 int lastExpandedGroupPosition
  • 关闭亮点

    我想关闭 PHPStorm 对非错误相关事物的烦人的突出显示 我读了他们的文档 其中说要转到首选项 gt 编辑器 gt 检查 我取消了 SQL 的所有选择 但我仍然无缘无故地得到绿色突出显示 我如何禁用此功能 这很让人分心 That s 语
  • 使用反射实例化内部类时出现 InstantiationException。为什么?

    我无法创建 B 对象 但为什么呢 public class AFactory public int currentRange private abstract class A protected final Object range cur