Java:泛型语法 [英] Java: Generics syntax
问题描述
这可以返回一个int列表:
public List< Integer> GetIListImpl(){
返回新的ArrayList< Integer>();
}
但是如果我想让调用者指定泛型类型呢?就像这样,尽管语法上我不知道该怎么做:
public List< T> GetIListImpl< T>(){
返回新的ArrayList< T>();
}
使用方法为:
列表< String> = GetIListImpl< String>();
通用 static 参数化类型的工厂方法
看起来你想编写方便的工厂方法来实例化泛型集合。
您可以编写像这样的泛型方法:
public static< T>列表与LT; T> newArrayList(){
return new ArrayList< T>();
}
public static< K,V>地图< K,V> newHashMap(){
返回新的HashMap< K,V>();
}
然后您可以简单地写:
//绝对是类型安全的!根本没有编译警告!
列表< String> names = newArrayList();
列表<整数> nums = newArrayList();
地图< String,List< String>> map = newHashMap();
请注意,在某些情况下,上述方法不一定要是 static
,你可以选择从方法中省略实现 class
名称,并只使用接口
名称(例如 newList
, newMap
)。
来自 Effective Java 2nd Edition 的认可
这种通用类型推断 static
工厂方法实际上被有效Java第二版认可;它具有作为书中讨论的第一个项的独特特权。
以下是来自的相关引号项目1:考虑静态
工厂方法而不是构造函数:
$ b
A static
工厂方法的优势在于它们减少了创建参数化类型实例的详细程度。
当你调用参数化类的构造函数时,不幸的是你必须指定类型参数,即使它们在上下文中是显而易见的。这通常要求您快速连续提供两次类型参数:
Map< String,List< String>> m =
new HashMap< String,List< String>>();
随着类型参数的长度和复杂度的增加,这个冗余规范很快就变得很痛苦。但是,使用 static
工厂,编译器可以为您找出类型参数。这被称为类型推断。例如,假设 HashMap
提供了这个 static
工厂:
public static< K,V>的HashMap< K,V> newInstance(){
返回新的HashMap< K,V>();
}
然后你可以用这个简洁的替代方式替换上面罗嗦的声明:
地图< String,List< String>> m = HashMap.newInstance();
不幸的是,标准的集合实现如 HashMap
在版本1.6中没有 static
工厂方法,但是您可以将这些方法放在您自己的实用程序类中。更重要的是,您可以在您自己的参数化类中提供这样的静态
工厂。
该项还为这些静态
工厂方法规定了通用命名约定:
-
getInstance
- 返回一个由参数描述的实例[/ b]
-
newInstance
- 像 getInstance
,除了它保证返回的每个实例都与其他实例不同。
-
new
类型
- 像 newInstance
,但在工厂方法处于不同类时使用。
$>
blockquote>
显式类型参数
您不必明确提供大多数情况下都是类型参数,因为Java泛型类型推理系统通常可以找出你需要的东西。然而,为了提供显式的类型参数,语法是把它之前方法名称(而不是之后)。下面是一个使用显式参数调用泛型方法< T>列表与LT; T> emptyList()
from java.util.Collections
:
集合<字符串>的emptyList();
// Collections.emptyList< String>();请注意,泛型方法调用的显式类型参数化的语法怪癖是:您必须限定类型(如果 static
)或您调用方法的对象,即使它们可以省略不是一个明确的参数化。
参考文献
附录:Guava收集工厂方法
需要注意的是 Guava 实际上已经为静态
工厂方法提供了 Java集合框架中的类型:
从主要 package com.google.common.collect
:
-
Lists.newArrayList()
, newLinkedList()
,...
-
Sets.newHashSet()
, newTreeSet()
, newEnumSet(...)
,...
-
Maps.newHashMap()
, newTreeMap()
, $ b $
$事实上,本着有效Java第二版推荐的精神,Guava自己的集合不提供 public
构造函数,而是提供 static create()
工厂方法:
库的其他部分还提供了很多高级有用的功能。
This works to return a list of ints:
public List<Integer> GetIListImpl() {
return new ArrayList<Integer>();
}
But what if I want to let the caller specify the generic type? Something like this, although syntactically I'm not sure how to do it:
public List<T> GetIListImpl<T>() {
return new ArrayList<T>();
}
The usage would be:
List<String> = GetIListImpl<String>();
解决方案 On generic static
factory methods for parameterized types
It looks like you want to write convenient factory methods to instantiate generic collections.
You can write generic methods like these:
public static <T> List<T> newArrayList() {
return new ArrayList<T>();
}
public static <K,V> Map<K,V> newHashMap() {
return new HashMap<K,V>();
}
Then you can simply write:
// absolutely type-safe!!! no compilation warnings at all!!!
List<String> names = newArrayList();
List<Integer> nums = newArrayList();
Map<String, List<String>> map = newHashMap();
Note that in some contexts, the above methods do not have to be static
, and you may opt to leave out the implementation class
names out of the methods and only use the interface
names (e.g. newList
, newMap
).
An endorsement from Effective Java 2nd Edition
This kind of generic type-inferring static
factory method is actually endorsed by Effective Java 2nd Edition; it had the unique privilege of being the very first item discussed in the book.
Here are the relevant quotes from Item 1: Consider static
factory methods instead of constructors:
A fourth advantage of static
factory methods is that they reduce the verbosity of creating parameterized type instances.
When you invoke the constructor of a parameterized class, unfortunately you must specify the type parameters even if they're obvious from context. This typically requires you to provide the type parameters twice in quick succession:
Map<String,List<String>> m =
new HashMap<String,List<String>>();
This redundant specification quickly becomes painful as the length and complexity of the type parameters increase. With static
factories, however, the compiler can figure out the type parameters for you. This is known as type inference. For example, suppose that HashMap
provided this static
factory:
public static <K,V> HashMap<K,V> newInstance() {
return new HashMap<K,V>();
}
Then you could replace the wordy declaration above with this succinct alternative:
Map<String,List<String>> m = HashMap.newInstance();
Unfortunately the standard collection implementations such as HashMap
do not have static
factory methods as of release 1.6, but you can put these methods in your own utility class. More importantly you can provide such static
factories in your own parameterized classes.
The item also prescribes the common naming convention for these static
factory methods:
getInstance
- returns an instance that is described by the parameters […]
newInstance
- Like getInstance
, except it guarantees that each instance returned is distinct from all others.
new
Type
- Like newInstance
, but used when the factory method is in a different class. Type
indicates the type of object returned by the factory method.
On explicit type parameters
You do not have to explicitly provide the type parameters in most cases, since the Java generics type inference system can usually figure out what you need.
Nevertheless, to provide explicit type parameters, the syntax is to put it before the method name (not after). Here's an example of invoking with explicit parameter the generic method <T> List<T> emptyList()
from java.util.Collections
:
Collections.<String>emptyList();
// Collections.emptyList<String>(); // DOES NOT COMPILE
Note that a syntax quirk of the explicit type parameterization for generic method invocation is that you must qualify the type (if static
) or the object that you're invoking the method on, even if they can be omitted if it was not an explicit parameterization.
References
Appendix: Collection factory methods from Guava
It should be noted that Guava in fact already provides the static
factory methods for the types in Java Collections Framework:
From the main package com.google.common.collect
:
Lists.newArrayList()
, newLinkedList()
, …
Sets.newHashSet()
, newTreeSet()
, newEnumSet(…)
, …
Maps.newHashMap()
, newTreeMap()
, newEnumMap(…)
, …
In fact, in the spirit of Effective Java 2nd Edition recommendation, Guava's own collections do not provide public
constructors, but instead provide static create()
factory methods:
HashMultiSet.create()
, a Multiset
implementation
TreeMultimap.create()
, a Multimap
implementation
The rest of the library also provides many highly useful functionality.
这篇关于Java:泛型语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
参数化类型的工厂方法
看起来你想编写方便的工厂方法来实例化泛型集合。
您可以编写像这样的泛型方法:
public static< T>列表与LT; T> newArrayList(){
return new ArrayList< T>();
}
public static< K,V>地图< K,V> newHashMap(){
返回新的HashMap< K,V>();
}
然后您可以简单地写:
//绝对是类型安全的!根本没有编译警告!
列表< String> names = newArrayList();
列表<整数> nums = newArrayList();
地图< String,List< String>> map = newHashMap();
请注意,在某些情况下,上述方法不一定要是 static
,你可以选择从方法中省略实现 class
名称,并只使用接口
名称(例如 newList
, newMap
)。
来自 Effective Java 2nd Edition 的认可
这种通用类型推断 static
工厂方法实际上被有效Java第二版认可;它具有作为书中讨论的第一个项的独特特权。
以下是来自的相关引号项目1:考虑静态
工厂方法而不是构造函数:
$ b
A static
工厂方法的优势在于它们减少了创建参数化类型实例的详细程度。
当你调用参数化类的构造函数时,不幸的是你必须指定类型参数,即使它们在上下文中是显而易见的。这通常要求您快速连续提供两次类型参数:
Map< String,List< String>> m =
new HashMap< String,List< String>>();
随着类型参数的长度和复杂度的增加,这个冗余规范很快就变得很痛苦。但是,使用 static
工厂,编译器可以为您找出类型参数。这被称为类型推断。例如,假设 HashMap
提供了这个 static
工厂:
public static< K,V>的HashMap< K,V> newInstance(){
返回新的HashMap< K,V>();
}
然后你可以用这个简洁的替代方式替换上面罗嗦的声明:
地图< String,List< String>> m = HashMap.newInstance();
不幸的是,标准的集合实现如 HashMap
在版本1.6中没有 static
工厂方法,但是您可以将这些方法放在您自己的实用程序类中。更重要的是,您可以在您自己的参数化类中提供这样的静态
工厂。
该项还为这些静态
工厂方法规定了通用命名约定:
-
getInstance
- 返回一个由参数描述的实例[/ b]
-
newInstance
- 像 getInstance
,除了它保证返回的每个实例都与其他实例不同。
-
new
类型
- 像 newInstance
,但在工厂方法处于不同类时使用。
$>
blockquote>
显式类型参数
您不必明确提供大多数情况下都是类型参数,因为Java泛型类型推理系统通常可以找出你需要的东西。然而,为了提供显式的类型参数,语法是把它之前方法名称(而不是之后)。下面是一个使用显式参数调用泛型方法< T>列表与LT; T> emptyList()
from java.util.Collections
:
集合<字符串>的emptyList();
// Collections.emptyList< String>();请注意,泛型方法调用的显式类型参数化的语法怪癖是:您必须限定类型(如果 static
)或您调用方法的对象,即使它们可以省略不是一个明确的参数化。
参考文献
附录:Guava收集工厂方法
需要注意的是 Guava 实际上已经为静态
工厂方法提供了 Java集合框架中的类型:
从主要 package com.google.common.collect
:
-
Lists.newArrayList()
, newLinkedList()
,...
-
Sets.newHashSet()
, newTreeSet()
, newEnumSet(...)
,...
-
Maps.newHashMap()
, newTreeMap()
, $ b $
$事实上,本着有效Java第二版推荐的精神,Guava自己的集合不提供 public
构造函数,而是提供 static create()
工厂方法:
库的其他部分还提供了很多高级有用的功能。
This works to return a list of ints:
public List<Integer> GetIListImpl() {
return new ArrayList<Integer>();
}
But what if I want to let the caller specify the generic type? Something like this, although syntactically I'm not sure how to do it:
public List<T> GetIListImpl<T>() {
return new ArrayList<T>();
}
The usage would be:
List<String> = GetIListImpl<String>();
解决方案 On generic static
factory methods for parameterized types
It looks like you want to write convenient factory methods to instantiate generic collections.
You can write generic methods like these:
public static <T> List<T> newArrayList() {
return new ArrayList<T>();
}
public static <K,V> Map<K,V> newHashMap() {
return new HashMap<K,V>();
}
Then you can simply write:
// absolutely type-safe!!! no compilation warnings at all!!!
List<String> names = newArrayList();
List<Integer> nums = newArrayList();
Map<String, List<String>> map = newHashMap();
Note that in some contexts, the above methods do not have to be static
, and you may opt to leave out the implementation class
names out of the methods and only use the interface
names (e.g. newList
, newMap
).
An endorsement from Effective Java 2nd Edition
This kind of generic type-inferring static
factory method is actually endorsed by Effective Java 2nd Edition; it had the unique privilege of being the very first item discussed in the book.
Here are the relevant quotes from Item 1: Consider static
factory methods instead of constructors:
A fourth advantage of static
factory methods is that they reduce the verbosity of creating parameterized type instances.
When you invoke the constructor of a parameterized class, unfortunately you must specify the type parameters even if they're obvious from context. This typically requires you to provide the type parameters twice in quick succession:
Map<String,List<String>> m =
new HashMap<String,List<String>>();
This redundant specification quickly becomes painful as the length and complexity of the type parameters increase. With static
factories, however, the compiler can figure out the type parameters for you. This is known as type inference. For example, suppose that HashMap
provided this static
factory:
public static <K,V> HashMap<K,V> newInstance() {
return new HashMap<K,V>();
}
Then you could replace the wordy declaration above with this succinct alternative:
Map<String,List<String>> m = HashMap.newInstance();
Unfortunately the standard collection implementations such as HashMap
do not have static
factory methods as of release 1.6, but you can put these methods in your own utility class. More importantly you can provide such static
factories in your own parameterized classes.
The item also prescribes the common naming convention for these static
factory methods:
getInstance
- returns an instance that is described by the parameters […]
newInstance
- Like getInstance
, except it guarantees that each instance returned is distinct from all others.
new
Type
- Like newInstance
, but used when the factory method is in a different class. Type
indicates the type of object returned by the factory method.
On explicit type parameters
You do not have to explicitly provide the type parameters in most cases, since the Java generics type inference system can usually figure out what you need.
Nevertheless, to provide explicit type parameters, the syntax is to put it before the method name (not after). Here's an example of invoking with explicit parameter the generic method <T> List<T> emptyList()
from java.util.Collections
:
Collections.<String>emptyList();
// Collections.emptyList<String>(); // DOES NOT COMPILE
Note that a syntax quirk of the explicit type parameterization for generic method invocation is that you must qualify the type (if static
) or the object that you're invoking the method on, even if they can be omitted if it was not an explicit parameterization.
References
Appendix: Collection factory methods from Guava
It should be noted that Guava in fact already provides the static
factory methods for the types in Java Collections Framework:
From the main package com.google.common.collect
:
Lists.newArrayList()
, newLinkedList()
, …
Sets.newHashSet()
, newTreeSet()
, newEnumSet(…)
, …
Maps.newHashMap()
, newTreeMap()
, newEnumMap(…)
, …
In fact, in the spirit of Effective Java 2nd Edition recommendation, Guava's own collections do not provide public
constructors, but instead provide static create()
factory methods:
HashMultiSet.create()
, a Multiset
implementation
TreeMultimap.create()
, a Multimap
implementation
The rest of the library also provides many highly useful functionality.
这篇关于Java:泛型语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!