Java中的通用方法和类型推理

鉴于以下不是非常有用的代码:

package com.something; import java.util.ArrayList; import java.util.Collection; //Not a generic class! public class Test { public  void plain(T param1, T param2) {} public  void fancy(T param1, Collection param2) {} public void testMethod() { //No error fancy("", new ArrayList()); //Compiler error here! fancy("", new ArrayList()); //No error plain("", new ArrayList()); } } 

(如果错了,请纠正我的理解!)

fancy()的第二次调用是一个编译器错误,因为Java无法推断两个参数之间的任何常见类型(不能推断Object因为第二个参数必须是Collection 。)

plain()的调用不是编译器错误,因为Java在两个参数之间推断出通用类型的Object

我最近遇到的代码具有类似于plain()的方法签名。

我的问题是:

plain()的签名对任何东西都有用吗?

也许编写该代码的人认为plain()的签名会强制两个参数在编译时具有相同的类型,显然不是这种情况。

使用plain()这样的签名编写方法有什么不同或有益,而不是仅将两个参数定义为Object s?

虽然编译器不会推断出一个人可能想要的generics类型,但它强制显式指定的类型约束。 以下调用会导致类型错误。

 this.plain("", new ArrayList()); /* Compiler error. */ 

参数化方法 plain(String,String)类型为Test不适用于参数(String,ArrayList

我想你可以说它可以作为某种文档,因此用户知道你希望两个参数都是相同的类型。 当然, 任何两个对象在某种程度上都是相同的类型(它们都是Object ),所以这是一个毫无意义的陈述。

长话短说,这是一个无用的签名。

当然,如果plain返回了类型T ,那将是一个不同的故事。

对fancy()的第二次调用是一个编译器错误,因为Java无法推断两个参数之间的任何常见类型(不能推断Object,因为第二个参数必须是Collection。)

好吧,我不确定这是什么原因,我想说原因是Collection中的generics类型T是一个不变量,其值决定了第一个参数T的类型。

例如,这是有效的:

 fancy("", new ArrayList()); //compiles Ok 

因为所有String都是CharSequences 。 一旦从ArraysList推断出类型,预期第一个参数是ArraysList

但是,这是无效的:

 fancy((CharSequence)"", new ArrayList()); //compiler error 

因为预期第一个参数的类型是String ,并且我们无法确保所有CharSequences实际上都是String类型,对吧?

因此,AFAIK,类型不兼容的原因是由于这种情况下generics的性质,而不是第二种类型是Collection的事实。