Java:泛型语法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3542139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:19:12  来源:igfitidea点击:

Java: Generics syntax

javagenerics

提问by Nick Heiner

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>();

回答by polygenelubricants

On generic staticfactory methods for parameterized types

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

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 classnames out of the methods and only use the interfacenames (e.g. newList, newMap).

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



An endorsement from Effective Java 2nd Edition

来自Effective Java 2nd Edition的认可

This kind of generic type-inferring staticfactory method is actually endorsed by Effective Java 2nd Edition; it had the unique privilege of being the very firstitem discussed in the book.

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

Here are the relevant quotes from Item 1: Consider staticfactory methods instead of constructors:

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

A fourthadvantage of staticfactory 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 staticfactories, however, the compiler can figure out the type parameters for you. This is known as type inference. For example, supposethat HashMapprovided this staticfactory:

    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 HashMapdo not have staticfactory methods as of release 1.6, but you can put these methods in your own utility class. More importantly you can provide such staticfactories in your own parameterized classes.

一个第四的优点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>();
    }

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

    Map<String,List<String>> m = HashMap.newInstance();

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

The item also prescribes the common naming convention for these staticfactory methods:

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

  • 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.
  • newType- Like newInstance, but used when the factory method is in a different class. Typeindicates the type of object returned by the factory method.
  • getInstance- 返回一个由参数描述的实例 […]
  • newInstance- 类似getInstance,除了它保证返回的每个实例都与所有其他实例不同。
  • newType- 类似newInstance,但在工厂方法在不同的类中时使用。Type表示工厂方法返回的对象类型。


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.

在大多数情况下,您不必显式提供类型参数,因为 Java 泛型类型推断系统通常可以确定您需要什么。

Nevertheless, to provide explicit type parameters, the syntax is to put it beforethe method name (not after). Here's an example of invoking with explicit parameter the generic method <T> List<T> emptyList()from java.util.Collections:

然而,要提供显式类型参数,语法是将它放在方法名称之前(而不是之后)。这里是有明确参数的泛型方法调用的一个例子<T> List<T> emptyList()来自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 mustqualify 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.

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



References

参考



Appendix: Collection factory methods from Guava

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

It should be noted that Guavain fact already provides the staticfactory methods for the types in Java Collections Framework:

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

From the main package com.google.common.collect:

从主要package com.google.common.collect

In fact, in the spirit of Effective Java 2nd Editionrecommendation, Guava's own collections do not provide publicconstructors, but instead provide static create()factory methods:

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

The rest of the library also provides many highly useful functionality.

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

回答by Colin Hebert

The syntax would be

语法是

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

You were close.

你很接近。

And the usage is more like :

用法更像是:

MyClass.<Integer>getIListImpl();

回答by josefx

First you have to specify the generic type on the method and not the class level.

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

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

Look at the position of the Generic type argument, it stands before the method name. For classes it stands behind the class name. So instead of adding the generic type after the method name you call it like this

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

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

You have to call it with either the class name or an instance. The compiler does not like the following:

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

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

Sometimes it works without the generic type

有时它可以在没有泛型类型的情况下工作

List<Integer> l = getListImpl()

Here the comparison class and method generic

这里比较类和方法泛型

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