63

我有一个定义两个重载方法的类

public void handle(Void e) 

protected void handle() 

显然它们是不同的,尤其handle(Void e)public


这两者有什么区别?

如何调用第一种方法?我正在使用handle(null)- 这是正确的吗?

4

4 回答 4

69

Void是一个通常仅用于反射的特殊类 - 它的主要用途是表示 void 方法的返回类型。从javadoc 为Void

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

因为Void无法实例化该类,所以您可以传递给具有Void类型参数的方法的唯一值,例如handle(Void e),是null


那是事件的官方版本,但是对于那些感兴趣的人,尽管在 的 javadoc 中声称相反Void,您实际上可以实例化 的实例Void

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框架。

于 2012-12-25T11:48:05.077 回答
46

第一个函数是单个参数的函数,必须提供并且只能有效地取值null。null 以外的任何值都不会编译。第二个函数不接受任何参数并且传递null给它不会编译。

于 2012-12-25T11:48:57.570 回答
15

考虑AsyncTask<T1, T2, T3>来自Android 系统的 API ,它提供了三个钩子:

class AsyncTask<S, T, V> {
  void doInBackground(S...);
  void onProgressUpdate(T...);
  void onPostExecute(V);
}

当您扩展泛型类型时AsyncTask<T1, T2, T3>,您可能对将参数用于进度结果挂钩不感兴趣,因此您的实现将如下所示:

class HTTPDownloader extends AsyncTask<URL, Void, Void> {
  void doInBackground(URL... urls) {}
  void onProgressUpdate(Void... unused) {}
  void onPostExecute(Void unused) {}
}

您可以使用参数调用这些方法null,因为Void无法实例化。

于 2012-12-25T12:10:28.507 回答
6

如果Void实际上不是类型参数的实例化(这显然是有意义的),那么声明一个handle(Void)如果您的handle方法受制于语言外契约的意义也很有意义,该契约说想要参与某个协议的对象必须实现单参数句柄方法,无论实际参数类型如何。现在,可能有一个特殊情况的实现不能处理任何事情,但是为这样的实现null声明是有意义handle(Void)的。

于 2012-12-25T12:08:47.413 回答