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
的事实。