Java泛型和静态工厂方法——语法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20751867/
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-08-13 04:05:23  来源:igfitidea点击:

Java Generics and Static Factory Methods -- Syntax

javagenericssyntaxstaticfactory

提问by FateNuller

Here's what I've got:

这是我所拥有的:

public class Node<T> {

    // instance variables
    private Node<T> next;
    private T data;

    // construct with data
    private Node(T data){
        next = null;
        this.data = data;
    }

    // construct without data
    private Node(){
        next = null;
        this.data = null;
    }

    // static factory method
    public static <T> Node<T> newNodeWithData(T data){
        return new Node<T>(data);
    }

    // static factory method
    public static <T> Node<T> newNode(){
        return new Node<T>();
    }
...
}

My question really just about the syntax of generics coupled with that of a static factory method. I don't really understand whywe put the < T > before the return type in the method declaration. Is it kind of like typecasting? Any help would be much appreciated!

我的问题实际上只是关于泛型的语法与静态工厂方法的语法相结合。我真的不明白为什么我们将 < T > 放在方法声明中的返回类型之前。这有点像类型转换?任何帮助将非常感激!

采纳答案by Brian Roach

What you're asking about is type inferrence.

您要问的是类型推断

Since it's a static method it has to infer the Generic type from somewhere; You don't have an instance of the class. That's what the <T>means.

由于它是一个静态方法,它必须从某个地方推断出 Generic 类型;您没有该类的实例。就是这个<T>意思。

In the case of your method that takes no arguments it's actually inferring it from the target of the assignment. For example, say your method looked like this:

对于不带参数的方法,它实际上是从赋值的目标中推断出来的。例如,假设您的方法如下所示:

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

When using this method, Tis inferred from the target (in this case String):

使用此方法时,T从目标推断(在本例中String):

List<String> myList = MyClass.getNewList();

In your other static method where you have a Generic argument, Tis being inferred from the type being passed in:

在您具有 Generic 参数的其他静态方法中,T是从传入的类型推断出来的:

public static <T> List<T> getNewListWithElement(T element) {
    List<T> list = new ArrayList<T>();
    list.add(element);
    return list;
}

Here, if you tried doing:

在这里,如果您尝试执行以下操作:

List<String> myList = MyClass.getNewListWithElement(new Integer(4));

It would tell you that your target type was wrong, and you needed a List<Integer>

它会告诉你你的目标类型是错误的,你需要一个 List<Integer>

Specifically this is covered in sections 15.12.2.7and 15.12.2.8of the JLS.

具体而言,这在 JLS 的第15.12.2.715.12.2.8节中有介绍

回答by Sibbo

The <T>is just the signal, that this method uses Tas type variable. Without it, the compiler would think, Tis a class, interfaceor enumthat is declared somewhere and output an error. It is not the same Tas used in your first line. You can replace the Tin this method with any other letter, maybe that helps understanding.

<T>只是此方法T用作类型变量的信号。没有它,编译器会认为T是 a classinterface或者enum在某处声明并输出错误。它与T第一行中使用的不同。您可以T用任何其他字母替换此方法中的,这可能有助于理解。

回答by Andrey Chaschev

This is an only way to parametrize a static method, as the original Tin the Node declaration is bound to instance fields and methods of the Node. So you could write:

这是参数化静态方法的唯一方法,因为TNode 声明中的原始方法绑定到 Node.js 的实例字段和方法。所以你可以写:

public static <T1> Node<T1> newNode(){
    return new Node<T1>();
}

The original Tis bound to an instance of Nodeclass and cannot be referenced in static context. This would result in a compilation error:

原件T绑定到Node类的实例,不能在静态上下文中引用。这将导致编译错误:

// ERROR
public static Node<T> newNode(){
    return new Node<T>();
}

回答by OldCurmudgeon

The reason you must decorate the static method with such sugar is because, as a static method, it does not inherit the Tfrom the declaration of the class.

必须用这样的糖装饰静态方法的原因是,作为静态方法,它不会T从类的声明中继承。

You could just as well do:

你也可以这样做:

// static factory methods
public static <Q> Node<Q> newNode(){
    return new Node<Q>();
}

public static Node<String> newStringNode(String s){
    return new Node<String>(s);
}

A simple narrative to the declaration may assist:

声明的简单叙述可能有助于:

// This static method would have a <T> parameter to the class if it was not static
public static <T> 
// It returns an object of type `Node` with generic parameter T
Node<T> newNode(){
    // And here it is doing it's business.
    return new Node<T>();
}

回答by danidacar

T inferred from parameter

从参数推断的 T

public static <T> List<T> getNewListWithElement(T element)

How can the compiler make the difference between T as a class and T as a generic argument? The solution is to use to specify T element is a generic and not a class/interface.

编译器如何区分 T 作为类和 T 作为泛型参数?解决方案是使用指定 T 元素是泛型而不是类/接口。

T inferred from usage

从用法推断的 T

public static <T1> Node<T1> newNode(){
    return new Node<T1>();
}

Who will be T1 inside the method body if no declaration would be made?

如果不进行声明,谁将成为方法主体内的 T1?