除了语法上的差异,什么情况下会使用通用接口而不是接受通用参数的方法?
public interface Flight<T>{
void fly(T obj);
}
结束
public interface Flight{
void <T> fly(T obj);
}
除了语法上的差异,什么情况下会使用通用接口而不是接受通用参数的方法?
public interface Flight<T>{
void fly(T obj);
}
结束
public interface Flight{
void <T> fly(T obj);
}
<T> void fly(T obj);
这样的方法表示调用者可以使用任何类型作为T
,而实现只能依赖于实际类型可以分配给Object
(就像声明了<T extends Object>
一样)。void fly(Object obj);
并没有什么不同,后者也允许任意对象。接口
上的类型参数是合同的一部分,并且可以由实现的interface
指定或限制:public interface Flight<T>{
void fly(T obj);
}
允许像这样的实现:
public class X implements Flight<String> {
public void fly(String obj) {
}
}
T
的类型。或者public class NumberFlight<N extends Number> implements Flight<N> {
public void fly(N obj) {
}
}
保持通用性但限制类型。
接口
的签名在它作为另一个方法签名的一部分时也很重要,例如:
public void foo(Flight<? super String> f) {
f.fly("some string value");
}
在这里,你需要传递给foo
的Flight
实现必须能够消费一个String
值,因此Flight<String>
或Flight<CharSequence>
或Flight<Object>
是足够的,但不是Flight<Integer>
。声明这样的合同需要在interface
上使用类型参数,而不是在interface
的方法上。
NumberFlight
甚至可以在不改变Flight
和<T>
之间的契约的情况下限制类型。那很有趣。我现在更加开明了,非常感谢! - yev当您期望大多数实现方法在实例化类时执行的操作是基于提供的类型时,应使用通用类型。
例如,ArrayList<E>
是一种通用类型,因为它的大多数操作(添加、获取、删除等)依赖于创建时指定的类型。
当类中仅有少数方法依赖于不同类型时,应使用通用方法。
您可以在Java Docs中了解更多关于通用类型的信息。
java.util.ArrayList<E>
作为例子。当你创建这个类型的变量时,必须指定T
的具体类型:ArrayList<String> list = new ArrayList<>();
当调用与类型 T
相关的 List
接口方法时,使用这些具体类型。当调用 add
方法时,只能将 String
对象添加到列表中。使用 get
从列表中检索元素时,您将获得具体类型为 String
的元素。
对于泛型方法,类型 T
仅针对该方法进行指定。如果方法返回该泛型类型的值,则更有意义。通常会发现如下代码:
MyObject obj = SomeClass.staticGenericMethod(MyObject.class)
或者
MyObject obj = classInstance.genericMethod(MyObject.class);
你应该以大写字母开头命名你的接口名称:Flight<T>