Java:泛型语法

Nic*_*ner 17 java generics

这可以返回一个int列表:

public List<Integer> GetIListImpl() {
    return new ArrayList<Integer>();
}
Run Code Online (Sandbox Code Playgroud)

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

public List<T> GetIListImpl<T>() {
    return new ArrayList<T>();
}
Run Code Online (Sandbox Code Playgroud)

用法是:

    List<String> = GetIListImpl<String>();
Run Code Online (Sandbox Code Playgroud)

pol*_*nts 25

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

看起来您想要编写方便的工厂方法来实例化泛型集合.

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

public static <T> List<T> newArrayList() {
    return new ArrayList<T>();
}
public static <K,V> Map<K,V> newHashMap() {
    return new HashMap<K,V>();
}
Run Code Online (Sandbox Code Playgroud)

然后你可以简单地写:

// absolutely type-safe!!! no compilation warnings at all!!!

List<String> names = newArrayList();

List<Integer> nums = newArrayList();

Map<String, List<String>> map = newHashMap();
Run Code Online (Sandbox Code Playgroud)

请注意,在某些情况下,上述方法不必如此static,您可以选择class从方法中省略实现名称,并仅使用interface名称(例如newList,newMap).


Effective Java 2nd Edition的认可

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

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

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

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

    Map<String,List<String>> m = 
        new HashMap<String,List<String>>();
Run Code Online (Sandbox Code Playgroud)

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

    public static <K,V> HashMap<K,V> newInstance() {
        return new HashMap<K,V>();
    }
Run Code Online (Sandbox Code Playgroud)

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

    Map<String,List<String>> m = HashMap.newInstance();
Run Code Online (Sandbox Code Playgroud)

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

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

  • getInstance - 返回参数[...]描述的实例
  • newInstance- 比如getInstance,除了它保证返回的每个实例都与其他实例不同.
  • newType- 比如newInstance,但是当工厂方法属于不同的类时使用.Type表示工厂方法返回的对象类型.

在显式类型参数上

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

然而,要提供显式类型参数,语法是将其放在方法名称之前(而不是之后).这里是有明确参数的泛型方法调用的一个例子<T> List<T> emptyList()来自java.util.Collections:

Collections.<String>emptyList();
// Collections.emptyList<String>(); // DOES NOT COMPILE
Run Code Online (Sandbox Code Playgroud)

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


参考


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

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

从主要package com.google.common.collect:

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

库的其余部分还提供了许多非常有用的功能.

  • @Colin:Apache Commons Collection并不是一般化的. (3认同)

Col*_*ert 8

语法是

public static <T> List<T> getIListImpl() {
    return new ArrayList<T>();
}
Run Code Online (Sandbox Code Playgroud)

你很亲密

用法更像是:

MyClass.<Integer>getIListImpl();
Run Code Online (Sandbox Code Playgroud)