我有一个定义了两个重载方法的类
public void handle(Void e)
protected void handle()
显然它们不同,尤其是handle(Void e)
是public
。
这两者有什么区别?
如何调用第一种方法?我正在使用handle(null)
- 这是正确的吗?
答案 0 :(得分:63)
Void
是一个通常仅用于反射的特殊类 - 它的主要用途是表示void方法的返回类型。来自javadoc for Void
:
Void类是一个不可实例化的占位符类,用于保存对表示Java关键字void的Class对象的引用。
由于无法实例化Void
类,因此您可以传递给具有Void
类型参数的方法的唯一值(例如handle(Void e)
)为null
。
这是事件的正式版本,但对于那些感兴趣的人,尽管在Void
的javadoc中声称相反,但可以实际实例化Void
的实例:< / p>
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
Void v = c.newInstance(); // Hello sailor!
也就是说,当你想表明该类型被“忽略”时,我已经看到Void
“有用”用作通用参数类型,例如:
Callable<Void> ignoreResult = new Callable<Void> () {
public Void call() throws Exception {
// do something
return null; // only possible value for a Void type
}
}
Callable
的泛型参数是返回类型,所以当像这样使用Void
时,对于代码的读者来说这是一个明确的信号,即返回值并不重要,即使使用需要Callable
接口,例如,如果使用Executor
框架。
答案 1 :(得分:40)
第一个函数是单个参数的函数,必须提供该参数,并且只能有效地取值null
。除null之外的任何值都不会编译。第二个函数不接受任何参数,并且将null
传递给它将无法编译。
答案 2 :(得分:14)
考虑来自the Android system的AsyncTask<T1, T2, T3>
的API,它提供了三个钩子:
class AsyncTask<S, T, V> {
void doInBackground(S...);
void onProgressUpdate(T...);
void onPostExecute(V);
}
当您扩展泛型类型AsyncTask<T1, T2, T3>
时,您可能对使用 progress 和 result 挂钩的参数不感兴趣,因此您的实现将如下所示:
class HTTPDownloader extends AsyncTask<URL, Void, Void> {
void doInBackground(URL... urls) {}
void onProgressUpdate(Void... unused) {}
void onPostExecute(Void unused) {}
}
并且您可以使用null
参数调用这些方法,因为Void
无法实例化。
答案 3 :(得分:6)
如果Void
实际上不是类型参数的实例化(显然有意义),那么如果handle(Void)
方法受到handle
方法的约束,则声明null
一个extralinguistic契约,表示想要参与某个协议的对象必须实现一个参数句柄方法,而不管实际的参数类型。现在,可能有一个特殊情况的实现无法处理除handle(Void)
以外的任何内容,因此为这样的实现声明{{1}}是有意义的。