Java Generics - 方法声明的区别

时间:2016-09-29 03:42:07

标签: java generics

以下两个方法声明之间有什么区别:

 1. <R> Stream<R> myFunc(Function<? super T, ? extends R> mapper);    
 2. Stream<R> myFunc(Function<? super T, ? extends R> mapper);

对于要编译的第二个声明,我需要像这样将类参数添加到类中。

public class MyGenericsTest<T, R>

在这种情况下,编译器确保在编译时确定myFunc的返回类型。编译器也可以从方法签名中知道。我很困惑为什么这两个声明被编译器区别对待。

2 个答案:

答案 0 :(得分:6)

通过编写header(),您告诉编译器:

  • <R> Stream<R> myFunc(Function<? super T, ? extends R> mapper)是任何一个类,并且是方法的本地方法(从开头的R开始)
  • 返回类型为<R>
  • Stream
  • RT的type参数中指定的类(如果你没有指定它,它就不会工作,因为编译器不会知道MyGenericsTest<T>

如果您更改为TStream<R> myFunc(Function<? super T, ? extends R> mapper)R不是本地的(方法开头没有T),编译器希望它们定义于课程级别为<R, T>

答案 1 :(得分:1)

第二种形式:

Stream<R> myFunc(Function<? super T, ? extends R> mapper);

与此无异:

Stream<String> myFunc(Function<? super T, ? extends String> mapper);

到编译器,除了它使用不同的类型。第二个返回String的流。第一个返回R的流,无论R是什么。编译器已经知道String是什么。对于第一个,编译器必须知道R是什么,这意味着它必须在某处定义。它可以是外部类的通用参数,但它也可以是从其他地方导入的非泛型类(由非常糟糕的人提出有意义的名称)。

请记住,虽然我们经常使用单个大写字母作为通用参数,但这只是一个人类惯例。编译器只是将其视为任何其他标识符。

但这就是为什么你的两个例子如此不同。第一个是定义方法的语法,它是一个泛型方法,带有您正在调用R的类型参数。第二个是与返回Stream<String>List<Integer>或其他内容的方法完全相同的语法。