Void真的是不可实例化的吗?



Void的javadoc表示:

Void类是一个不可实例化的占位符类,用于保存对表示Java关键字Void的class对象的引用。

但是构造函数很简单:

private Void() {}

,下面的代码实例化了一个Void:

Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor

所以Void而不是不可实例化的

是否有办法使Void真正不可实例化?

Rohit非常正确,抛出异常"足够好";对于大多数用例。但是,使用sun.misc.Unsafe:

似乎可以绕过这个问题。

public native Object allocateInstance(Class Class)抛出InstantiationException

分配一个实例但不运行任何实例构造函数。如果类尚未初始化,则初始化该类。

(注意,我还没有实际测试这是否有效)

将构造函数设置为私有,并且不允许任何其他可以被外部访问的构造函数,这会使类不可实例化

但是,您不能避免使用Reflection API访问它。使用反射,您可以做通常不允许的事情。

但是,如果你真的希望你的类是不可实例化的,即使通过反射,你可以从构造器throw Unchecked Exception

private MyClass() {
    throw UnsupportedOperationException("Can't instantiate class");
}

在这种情况下,当您使用Constructor#newInstance()方法创建实例时,它将抛出InvocationTargetException,如@Alex在注释中引用的。

下面是Constructor#newInstance()方法的文档,它声明了要抛出的异常列表,其中一个是InvocationTargetException,它说:-

抛出:
InvocationTargetException -如果底层构造函数抛出异常。

反射API打破了这样的各种"规则",就像能够修改final字段一样。有很多人抱怨它允许你打破Java的硬性规则,但事实就是这样。

没有反射(或@StevenSchlansker的疯狂的Unsafe API下面发布),它是不可能实例化的。但是,只要允许反射,这些变通方法就会存在。

在Oracle自己的反射教程中,他们列出了反射的优点和缺点。哪一个更大由你来决定。

还有,看看这个问题:什么是反射,它为什么有用?

相关内容

  • 没有找到相关文章

最新更新