Java 之间的差异<;T扩展A>;无效foo(T)和无效foo(A)

Java 之间的差异<;T扩展A>;无效foo(T)和无效foo(A),java,generics,Java,Generics,假设A是一个接口。两者的区别是什么 public <T extends A> void foo(T t) { ... } ?使用一个对象时没有区别。但是想象一下如果你有 class B extends A { ... } 及 publicsvoidf(列表){…}; 及 publicsvoidf(列表){…}; 使用第一个,您可以传递一个类型为list的列表。对于第二个,您可以传递一个列表,其中包含扩展a的对象。然而,对于第一个,你不能做同样的事情。换句话说,您不能将List

假设
A
是一个接口。两者的区别是什么

public <T extends A> void foo(T t) { ... }

使用一个对象时没有区别。但是想象一下如果你有

class B extends A { ... }

publicsvoidf(列表){…};

publicsvoidf(列表){…};
使用第一个,您可以传递一个类型为
list
的列表。对于第二个,您可以传递一个列表,其中包含扩展
a
的对象。然而,对于第一个,你不能做同样的事情。换句话说,您不能将
List
传递给第一个方法,但可以传递给第二个方法

不多

另一方面,考虑这种方法:

public <T extends A> T transform(T t);
若您将方法声明为,那个么它是不可能的(上面的方法不会编译,因为编译器会强制您将
result
类型声明为
A

public A transform(A a)

在您的案例中没有区别,因为类型参数仅在一个地方使用。这两个方法都将接受A或扩展A的任何内容。在这种情况下,泛型方法更有意义,因为类型参数允许您将返回值绑定到传递的参数:

public <T extends A> T f(Class<T>) {...}
publicttf(类){…}

它是否起作用取决于该函数内部的内容

泛型的要点是确保类型安全。假设A有两个子类,我们称它们为B和C。在第一个示例中,使用f(List),列表可以包括B、C或两者的混合。但是在第二个例子f(List)中,当我们调用函数时,我们必须指定类型。如果我们说f,那么我们知道这是一个B的列表,不允许有C。我们不允许通过C或通用a的列表,我们不能在列表中添加任何C,我们取出的任何东西都将保证为B


这是好是坏取决于你想做什么。如果您想要一个全部为B或全部为C的列表,那么泛型有助于保证这一点。如果你想要一个可以是两者混合的列表,那么你不想使用泛型,使用简单的f(列表)。

如果你有一个返回类型,这也是正确的。“如果你声明f为,
f
是什么意思?对于第二种情况,你仍然可以通过“示例”编写
public void f(列表)你指的是什么示例我指的是原始海报上给出的两个函数声明:“f(列表)”和“f(列表)”。好吧,也许它们不是真正的“示例”。我在问题中看不到这一点;只有在其中一个答案中,问题开始了,“假设A是一个接口。两者之间有什么区别”。下一行是我称为A的第一个函数声明“示例”。然后它说“或”,他给出了下一个示例。这篇文本在您的浏览器中显示不正确,还是我们彼此不理解?他的问题中没有
List
List
;只有
T
A
public <T extends A> T transform(T t);
class B implements A { ... }
B result = transform(new B(...));
public A transform(A a)
public <T extends A> T f(Class<T>) {...}