Void真的不可以实现吗?
Void
的javadoc说:
Void类是一个不可实例化的占位符类,用于保存对表示Java关键字void的Class对象的引用。
但构造函数很简单:
private Void() {}
并且此代码实例化了一个Void
:
Constructor c = Void.class.getDeclaredConstructor(); c.setAccessible(true); Void v = c.newInstance(); // Hello sailor
所以Void
不是不可实现的。
是否有办法让Void
真正无法实现?
使您的构造函数成为私有,并且没有任何其他可以被外部访问的构造函数,这使得类不可实例化 。
但是,您无法避免使用Reflection API
访问它。 使用reflection,你可以做,通常不允许的。
但是,如果你真的希望你的类是不可实现的 ,即使通过Reflection ,你也可以从构造函数中 throw
一个Unchecked Exception 。
private MyClass() { throw UnsupportedOperationException("Can't instantiate class"); }
在这种情况下,当您使用Constructor#newInstance()
方法创建实例时,它将抛出InvocationTargetException
,如@Alex的注释所引用。
这是Constructor#newInstance()
方法的文档,它声明了要抛出的exception列表,其中一个是InvocationTargetException
,它说:
抛出:
InvocationTargetException – 如果底层构造函数抛出exception。
Rohit非常正确,对于大多数用例而言,抛出exception“足够好”。 但是, 使用sun.misc.Unsafe看起来甚至可以绕过它。
public native Object allocateInstance(Class cls)抛出InstantiationException
分配实例但不运行任何构造函数。 如果尚未归类,则初始化该类。
(注意,我实际上没有测试过这是否有效)
Reflection API打破了这样的各种“规则”,就像能够修改final
字段一样。 有很多人抱怨它可以让你打破Java的严格规则,但事实就是如此。
如果没有Reflection(或者下面发布的@ StevenSchlansker疯狂的Unsafe
API),就不可能实例化。 但是,只要允许reflection,这些变通方法就会存在。
在Oracle自己的Reflection教程中 ,他们列出了优点和缺点。 由你决定哪个更大。
另外,请看这个问题: 什么是反思,为什么它有用?