这可以返回一个int列表:
public List<Integer> GetIListImpl() {
return new ArrayList<Integer>();
}
但是如果我想让调用者指定泛型类型呢?像这样的东西,虽然从语法上来说我不知道怎么做:
public List<T> GetIListImpl<T>() {
return new ArrayList<T>();
}
用法是:
List<String> = GetIListImpl<String>();
答案 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} }名称(例如interface
,newList
)。
这种通用类型推断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实际上已经为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自己的集合不提供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();