Java:泛型语法

时间:2010-08-22 15:55:35

标签: java generics

这可以返回一个int列表:

public List<Integer> GetIListImpl() {
    return new ArrayList<Integer>();
}

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

public List<T> GetIListImpl<T>() {
    return new ArrayList<T>();
}

用法是:

    List<String> = GetIListImpl<String>();

3 个答案:

答案 0 :(得分: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>();
}

然后你可以简单地写:

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

List<String> names = newArrayList();

List<Integer> nums = newArrayList();

Map<String, List<String>> map = newHashMap();

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


来自 Effective Java 2nd Edition

的认可

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

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

  

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

     

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

static
     

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

static
     

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

    public static <K,V> HashMap<K,V> newInstance() {
        return new HashMap<K,V>();
    }
     

不幸的是,从版本1.6开始,标准集合实现(例如 Map<String,List<String>> m = HashMap.newInstance(); )没有HashMap工厂方法,但您可以将这些方法放在您自己的实用程序类中。更重要的是,您可以在自己的参数化类中提供此类static工厂。

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

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

关于显式类型参数

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

然而,要提供显式类型参数,语法是将放在方法名称之前(而不是之后的)。以下是使用显式参数调用java.util.Collections中的通用方法Type的示例:

<T> List<T> emptyList()

请注意,泛型方法调用的显式类型参数化的语法怪癖是必须限定类型(如果Collections.<String>emptyList(); // Collections.emptyList<String>(); // DOES NOT COMPILE )或您正在调用方法的对象,即使它们不是明确的参数化也可以省略。


参考


附录:来自Guava的收集工厂方法

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

来自主package com.google.common.collect

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

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

答案 1 :(得分:8)

语法为

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

你很亲密。

用法更像是:

MyClass.<Integer>getIListImpl();

答案 2 :(得分:1)

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

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

查看Generic类型参数的位置,它位于方法名称之前。对于类,它位于类名后面。因此,不要在方法名称之后添加泛型类型,而是将其称为

List<Integer> l = Test.<Integer>getListImpl()

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

List<Integer> l = <Integer>getListImpl()

有时它没有通用类型

List<Integer> l = getListImpl()

这里比较类和方法通用

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