2

考虑这个通用方法取自Effective Java:

  // Generic method
    public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
     Set<E> result = new HashSet<E>(s1);
     result.addAll(s2);
     return result;
    }

而这个方法来练习上面的通用方法:

// Simple program to exercise generic method
public static void main(String[] args) {
 Set<String> guys = new HashSet<String>(
 Arrays.asList("Tom", "Dick", "Harry"));
 Set<String> stooges = new HashSet<String>(
 Arrays.asList("Larry", "Moe", "Curly"));
 Set<String> aflCio = union(guys, stooges); //What does the type parameter help here?
 System.out.println(aflCio);
}

如果我们没有提供类型参数,即<E>在修饰符和返回类型之间,我们仍然可以不将aflCio类型的引用分配给Set<String>联合方法的返回值吗?在这里购买我们的类型参数是什么?

我很难理解以下段落:

泛型方法的一个值得注意的特性是,您不需要像调用泛型构造函数时那样显式指定类型参数的值。编译器通过检查方法参数的类型来计算类型参数的值。在上面的程序中,编译器看到 union 的两个参数都是 Set 类型,所以它知道类型参数 E 必须是 String。这个过程称为类型推断。

我们不是将返回类型中的类型参数提到为Set<E>. 那么为什么我们需要再次添加它呢?

4

4 回答 4

4

也许理解这一点的最简单方法是考虑替代方案。如果不使用泛型方法,则必须为Set.

Object不是一个有效的选择,因为您不想Set<Object>从您的方法中接收 a - 您不能将其分配给 a Set<String>

// Nope 
public static Set<Object> union(Set<Object> s1, Set<Object> s2) {
  Set<Object> result = new HashSet<Object>(s1);
  result.addAll(s2);
  return result;
}

通配符?类型也不合适。同样,您无法将其分配给Set<String>.

相反,Java 定义了一个通用方法的语法,该方法正是为这种情况而设计的。

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
  Set<E> result = new HashSet<E>(s1);
  result.addAll(s2);
  return result;
}

现在我们不关心在 中存储什么类型Set,只要在两个输入中使用相同的类型。然后编译器知道Set<String>如果输入是Set<String>s,则返回类型将是。

于 2013-02-21T10:10:49.820 回答
4

如果您要问为什么必须编写<E>,那是因为这正是 Java 通用语法的定义方式。否则它不会编译,因为在这种情况下必须声明类型参数。

如果您要问绑定完成了什么:它所做的最相关的事情是确保两个参数是Set同一事物的 s 并且返回值包含相同类型的事物。

没有这个,您当然仍然可以设法合并两组字符串。毕竟人们在 Java 1.4 的日子里管理它。但是编译器无法为您检查。没有这个,您仍然可以将结果转换为正确的泛型类型,但是,您必须进行转换。

于 2013-02-21T10:24:53.603 回答
2

参数<E>让编译器知道您不会在List<E>like中指定真实的类名List<String>,而是使用类型变量 E

于 2013-02-21T10:19:39.343 回答
0

这给你带来了TypeSafetyTypeSafety确保

  • 传递的参数和函数的返回类型是正确的数据类型。
  • 一个类处理正确数据类型的对象。

这在您必须使用其他开发人员编写的类和函数的大型项目中非常重要。无需深入研究函数或类定义,您就可以传递/获取正确数据类型的对象,而不必担心由于ClassCastExceptions.

于 2013-02-21T10:28:26.443 回答