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

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()这样的方法与仅将两个参数定义为Object之间是否有任何区别或好处?

真正的泛型编程只是在Java中存在。 - SwiftMango
3个回答

4

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

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

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

有道理!这就是我一直在寻找的缺失部分。谢谢! - segfault
好的;我们必须调用 className 而不是 this。 - Kanagavelu Sugumar

3
我想你可以把它当作某种文档,以便用户知道您期望两个参数是相同类型的。当然,任何两个对象在某种程度上都是相同类型的(它们都是Object),因此这是一个毫无意义的声明。
长话短说,这是一个无用的签名。
当然,如果plain返回类型T,那就是另一回事了。

只是好奇,你能否详细讲述一下那个故事。 - Kanagavelu Sugumar
@KanagaveluSugumar 您需要详细说明哪个具体部分? - yshavit
如果 plain 返回了类型 T,会有什么影响?如果没有返回呢? - Kanagavelu Sugumar
如果 plain 返回了 T,那么在 Java 7 中,T 的类型将仅从参数中推断出来,并且返回值必须是相同的类型。在 Java 8 中,我认为这方面有所放宽。但是,如果它不返回类型,只是用作参数类型,那么 Java 将尝试推断任何类型,只要该类型是两个参数的超类。由于所有类都扩展自 Object,因此可以保证推断有效,但不能保证会给您任何有意义的东西。意图可能是“相同类型的两个参数”,但这不是您将得到的内容。 - yshavit

1
第二次调用fancy()是编译错误,因为Java无法推断出两个参数之间的任何公共类型(不能推断出Object,因为第二个参数必须是Collection)。我不确定这是否是原因,我认为原因是Collection中的泛型类型T是一个不变量,其值确定了第一个参数T的类型。例如,以下是有效的:
fancy("", new ArrayList<CharSequence>()); //compiles Ok

因为所有的String都是CharSequence。一旦从ArraysList<CharSequence>中推断出类型,第一个参数应该是CharSequence
然而,这是无效的:
fancy((CharSequence)"", new ArrayList<String>()); //compiler error

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

所以,据我所知,类型不兼容的原因是由于泛型在这种情况下的本质,而不是第二个类型是Collection的事实。


有道理。这个想法我也有过,但我没有深入去做出类似于你指出的“有效”示例。非常感谢纠正我的理解! - segfault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接