为什么静态泛型方法应该在返回类型前面有<T>

JHu*_*ter 2 java generics

为什么泛型静态方法除了返回类型之外还有一个实例方法?

public class Main<T> {
    public  static <T> T met(T t) {
        return t;
    }

    public  T met1(T t) {
        return t;
    }
}
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 7

实例方法也可以在<T>返回类型前面定义泛型类型参数(),但它不必,因为它可以使用已经在类级别(public class Main<T>)中定义的泛型类型参数.

另一方面,静态方法不能使用类级别中定义的泛型类型参数,因此它必须声明它打算使用的任何泛型类型参数.

即以下两者均有效

public static <T> T met(T t) {
    return t;
}

public <T> T met1(T t) {
    return t;
}
Run Code Online (Sandbox Code Playgroud)

另一方面,在下面

public static T met(T t) {
    return t;
}
Run Code Online (Sandbox Code Playgroud)

T 假定是类型标识符(即某个类或接口的名称),而不是泛型类型参数.


OLI*_*KOO 5

首先,我们需要了解什么是“加法”。它不是返回类型的补充。它是一个“有界类型参数

有界类型参数 有时您可能希望限制可用作参数化类型中的类型参数的类型。例如,对数字进行操作的方法可能只想接受 Number 或其子类的实例。这就是有界类型参数的用途。

当您编译通用类/方法/接口时。Java 编译器将泛型类型转换为 JVM 能够理解的代码。这个过程是调用类型擦除,它需要知道泛型类型参数的边界。即<T>get 转换为Object因为它是无界的并且<T extends Comparable<T>>get 转换为Comparable


其次,为什么泛型static方法需要有界类型参数而泛型实例方法不需要?

这种与类方法和实例方法的区别密切相关。

  • 当您使用关键字时,static该方法就变成了类方法。这意味着您可以在不创建实例的情况下进行调用。这就是问题所在。因为static方法在类的所有实例(包括不同类型参数的实例)之间共享,所以在实例化类型之前,Java 不知道 T 是什么。我们需要明确地告诉编译器类方法应该期望什么实例。

  • 当您不使用关键字时,static该方法现在是一个实例方法。这意味着在创建类的实例之前不能调用该方法。创建实例时,您需要指定类型参数。当您调用实例方法时,Java 编译器可以固有地使用该类型参数,因此有界类型参数对于实例方法是可选的。