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

时间:2017-08-13 05:57:52

标签: java generics

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

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

    public  T met1(T t) {
        return t;
    }
}

3 个答案:

答案 0 :(得分:6)

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

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

即。以下两个都是有效的

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

public <T> T met1(T t) {
    return t;
}

另一方面,在以下

public static T met(T t) {
    return t;
}
假设

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

答案 1 :(得分:3)

首先,我们需要了解什么是“添加”。它不是返回类型的补充。这是一个“Bounded Type Parameters

  

有界类型参数有时可能需要限制   可以在参数化类型中用作类型参数的类型。   例如,对数字进行操作的方法可能只想要   接受Number或其子类的实例。这是有限的   类型参数适用于。

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

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

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

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

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

答案 2 :(得分:0)

这有两个方面:

A)

实例方法隐式获取所有类类型参数,而静态方法不是。这样做的原因是,在编译时,分配给这些类型参数的类型特定于每个对象实例引用,因此它们永远不会应用于静态方法,因为它们不具有与之关联的特定实例。

B)

所有方法,实例或类都可以定义仅适用于该方法的其他类型参数。它们放在修饰符(publicstatic,...)和返回类型之间。这只是Java语言开发人员做出的任意语法选择。所以他们可以用不同的方式完成它,但是在使用之前必须声明一些东西更有意义(例如在参数类型声明中)。