当方法只有一个泛型类型时,使方法泛型有什么意义?



如果方法定义为:

<T> List<T> transform(List<T> list)

第一个 T 增加了什么?因为它本质上与:

List<T> transform(List<T> list)

区别在于T的范围。它可以在类级别或为每个单独的方法定义。

List<T> transform(List<T> list)

这个返回并接受List<T>其中所有方法的T都相同。

<T> List<T> transform(List<T> list)

此方法有自己的T与其类的泛型类型(如果有)无关。

<T>

是定义。在使用泛型类型参数之前,需要定义泛型类型参数,就像在使用泛型类型参数之前必须定义变量一样。


请记住,T只是一个命名约定。该标识符可以是任何内容。可能是<F><Foo>.

假设他们按照您的建议实现了它,并且编译器只是将任何缺少的类型推断为泛型类型参数。假设我有一个自定义类Foo我忘记导入它。

List<Foo> transform(List<Foo> list)

编译器会说"好吧,我不知道Foo是什么,所以让我们假设它是一个通用参数"。然后,您的方法可以很好地编译,而您更希望编译器已捕获该错误。

或者,也许您认为T应该是一个特例。然后,您将采用目前只是约定的东西,并将其作为语言的特殊部分。您必须处理有人创建名为T的真实类的可能性。

因此,明确的声明有其用途,即使它们有时看起来很冗长。

<T> List<T> transform(List<T> list)

因为它本质上与:

List<T> transform(List<T> list)

不是。

在第二种情况下,必须在包含类上定义T

class GenericClass<T> {
List<T> transform(List<T> list) { ... }
}

然后,您只能传入/获取与类相同的元素类型的列表:

GenericClass<String> genericClass = new GenericClass<>();
List<String> stringList = genericClass.transform(Arrays.asList(""));  // OK.
List<Integer> intList = genericClass.transform(Arrays.asList(0));  // Error!

但是,对于第一种形式,T不是在类上定义的,因此每次调用时它可能不同:

class NonGenericClass {
<T> List<T> transform(List<T> list) { ... }
}
NonGenericClass nonGenericClass = new NonGenericClass();
List<String> stringList = nonGenericClass.transform(Arrays.asList(""));  // OK.
List<Integer> intList = nonGenericClass.transform(Arrays.asList(0));  // OK.

这根本不一样。

<T>声明变量,其余的是变量的使用。这直接编译失败:

public class Example {
public List<T> transform(List<T> foo) {}
}

试试吧。

如果这是您拥有的:

public class Example<T> {
public <T> List<T> transform(List<T> foo) {}
}

然后你有 2 个不相关的类型变量,不幸的是都命名为T,这非常令人困惑;我强烈建议你不要这样做(类定义了 a,然后方法定义了自己的 T,确保该方法声明中 T 的所有用法都被假定为在方法上定义;类定义的不再可访问;它已被"阴影化"。从这个意义上说,它等同于:

public class Example {
int x;
public void foo(int x) { }
}

foo 的int xint x;字段完全无关,但由于它们具有相同的名称,因此您无法引用名为x的字段。至少为此有一个转义(this.x仍然指字段) - 泛型没有这样的奢侈,所以,不要像这样阴影变量。

如果你有这段代码,你根本不需要在方法上有一个 var 类型;但如果你真的这样做,不要使用 T,而是使用其他任何东西:

public class Foo<T> {
public <Y> List<Y> transform(List<Y> foo) {}
}

如前所述,以下内容基本相同。

<T> List<T> transform(List<T> list)
List<T> transform(List<T> list)

但前者也允许人们进一步约束T。 例如,你可以做

<T extends Foo> List<T> transform(List<T> list) {
...   
}

如果 T 子类 Foo,则只能传递List<T>

最新更新