以下两个方法声明之间有什么区别:
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的返回类型。编译器也可以从方法签名中知道。我很困惑为什么这两个声明被编译器区别对待。
答案 0 :(得分:6)
通过编写header()
,您告诉编译器:
<R> Stream<R> myFunc(Function<? super T, ? extends R> mapper)
是任何一个类,并且是方法的本地方法(从开头的R
开始)<R>
Stream
R
是T
的type参数中指定的类(如果你没有指定它,它就不会工作,因为编译器不会知道MyGenericsTest<T>
)如果您更改为T
,Stream<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>
或其他内容的方法完全相同的语法。