8

鉴于以下不太有用的代码:

package com.something;

import java.util.ArrayList;
import java.util.Collection;

//Not a generic class!
public class Test {

  public <T> void plain(T param1, T param2) {}
  public <T> void fancy(T param1, Collection<T> param2) {}

  public void testMethod() {

    //No error
    fancy("", new ArrayList<String>());

    //Compiler error here!
    fancy("", new ArrayList<Integer>());

    //No error
    plain("", new ArrayList<Integer>());

  }

}

(如有错误,请纠正我的理解!)

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

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

我最近遇到了具有类似于plain().

我的问题是这样的:

plain()的签名对任何事情都有用吗?

也许编写该代码的人认为plain()' 的签名会强制两个参数在编译时具有相同的类型,但显然情况并非如此。

编写带有类似签名的方法plain()而不是仅仅将两个参数都定义为Objects 有什么区别或好处吗?

4

3 回答 3

4

虽然编译器不会推断出人们可能想要的泛型类型,但它强制执行明确指定的类型约束。以下调用导致类型错误。

this.<String>plain("", new ArrayList<Integer>()); /* Compiler error. */

Test 类型的参数化方法 <String>plain(String, String) 不适用于参数 (String, ArrayList<Integer>)

于 2012-07-16T23:46:39.007 回答
3

我想您可以说它充当某种文档,以便用户知道您希望两个参数属于同一类型。当然,任何两个对象在某种程度上都属于同一类型(它们都是Object),所以这是一个没有意义的陈述。

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

当然,如果plain返回一个 type T,那就另当别论了。

于 2012-07-16T22:55:55.227 回答
1

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

好吧,我不确定这是否是原因,我会说原因是泛型类型TinCollection<T>是一个不变量,其值决定了第一个参数的类型T

例如,这是有效的:

fancy("", new ArrayList<CharSequence>()); //compiles Ok

因为String都是CharSequencesCharSequence一旦从 推断出类型,预计第一个参数是 a ArraysList<CharSequence>

但是,这是无效的:

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

因为预计第一个参数的类型是 be String,我们不能确保实际上所有CharSequences的都是 type String,对吧?

因此,AFAIK,类型不兼容的原因是在这种情况下是由于泛型的性质,而不是因为第二种类型是Collection.

于 2012-07-16T23:17:58.483 回答