Java:generics语法

这可以返回一个int列表:

public List GetIListImpl() { return new ArrayList(); } 

但是如果我想让调用者指定generics类型呢? 像这样的东西,虽然从语法上来说我不知道​​怎么做:

 public List GetIListImpl() { return new ArrayList(); } 

用法是:

  List = GetIListImpl(); 

关于参数化类型的通用static工厂方法

看起来您想编写方便的工厂方法来实例化generics集合。

您可以编写如下通用方法:

 public static  List newArrayList() { return new ArrayList(); } public static  Map newHashMap() { return new HashMap(); } 

然后你可以简单地写:

 // absolutely type-safe!!! no compilation warnings at all!!! List names = newArrayList(); List nums = newArrayList(); Map> map = newHashMap(); 

请注意,在某些上下文中,上述方法不必是static ,您可以选择从方法中省略实现class名称,并仅使用interface名称(例如newListnewMap )。


Effective Java 2nd Edition的认可

这种通用类型推断static工厂方法实际上得到了Effective Java 2nd Edition的认可; 它具有作为本书中讨论的第一个项目的独特特权。

以下是第1项中的相关引用:考虑static工厂方法而不是构造函数

static工厂方法的第四个优点是它们减少了创建参数化类型实例的详细程度。

当你调用参数化类的构造函数时,遗憾的是你必须指定类型参数,即使它们在上下文中是显而易见的。 这通常要求您快速连续两次提供类型参数:

  Map> m = new HashMap>(); 

随着类型参数的长度和复杂性的增加,这种冗余规范很快变得痛苦。 但是,对于static工厂,编译器可以为您确定类型参数。 这称为类型推断 。 例如, 假设 HashMap提供了这个static工厂:

  public static  HashMap newInstance() { return new HashMap(); } 

然后你可以用这个简洁的替代方案替换上面的罗嗦声明:

  Map> m = HashMap.newInstance(); 

遗憾的是,自版本1.6起,标准集合实现(如HashMap没有static工厂方法,但您可以将这些方法放在自己的实用程序类中。 更重要的是,您可以在自己的参数化类中提供此类static工厂。

该项还规定了这些static工厂方法的通用命名约定:

  • getInstance – 返回参数[…]描述的实例
  • newInstance – 与getInstance类似,但它保证返回的每个实例都与其他实例不同。
  • new Type – 与newInstance类似,但在工厂方法位于不同类时使用。 Type表示factory方法返回的对象类型。

关于显式类型参数

在大多数情况下,您不必显式提供类型参数,因为Javagenerics类型推断系统通常可以找出您需要的内容。

然而,要提供显式类型参数,语法是将其放在方法名称之前 (而不是之后 )。 下面是使用显式参数调用java.util.Collections的generics方法 List emptyList()

 Collections.emptyList(); // Collections.emptyList(); // DOES NOT COMPILE 

请注意,generics方法调用的显式类型参数化的语法怪癖是您必须限定类型(如果是static )或您正在调用该方法的对象,即使它们不是显式参数化也可以省略它们。


参考

  • Angelika Langer的Javagenerics常见问题解答
    • 什么是通用方法?
    • 什么是类型参数推断?
    • 什么是显式类型参数规范?
  • JLS 8.4.4通用方法

附录:番石榴的收集工厂方法

应该注意的是, Guava实际上已经为Java Collections Framework中的类型提供了static工厂方法:

从主要package com.google.common.collect

  • Lists.newArrayList()newLinkedList() ,…
  • Sets.newHashSet()newTreeSet()newEnumSet(…) ,…
  • Maps.newHashMap()newTreeMap()newEnumMap(…) ,…

实际上,根据Effective Java 2nd Edition的推荐精神,Guava自己的集合不提供public构造函数,而是提供static create()工厂方法:

  • HashMultiSet.create() ,一个Multiset实现
  • TreeMultimap.create() ,一个Multimap实现

库的其余部分还提供了许多非常有用的function。

语法是

 public static  List getIListImpl() { return new ArrayList(); } 

你很亲密

用法更像是:

 MyClass.getIListImpl(); 

首先,您必须在方法上指定generics类型,而不是类级别。

 class Test { public static  List getListImpl() { return new ArrayList(); } } 

查看Generic类型参数的位置,它位于方法名称之前。 对于类,它位于类名后面。 因此,不是在方法名称之后添加generics类型,而是像这样调用它

 List l = Test.getListImpl() 

您必须使用类名或实例来调用它。 编译器不喜欢以下内容:

 List l = getListImpl() 

有时它没有generics类型

 List l = getListImpl() 

这里的比较类和方法通用

 class Test{}//Generic after class name T t = new T(); void  methName(){}//Generic before method name t.methName();