我不知道为什么这段代码能正常工作。
static <T> int compare(T t1, T t2) {
return 0;
}
public static void main(String[] args) {
compare(new Thread(), new StringBuilder());
}
因为当我们遇到这样的事情时:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
return;
}
public static void main(String[] args) {
fromArrayToCollection(new Thread[] {}, new ArrayList<StringBuilder>()); // error
}
我们有一个错误。 为什么在第一个示例中编译器不检查两个参数的匹配?对不起,愚蠢的问题。
答案 0 :(得分:5)
泛型是不变,而不是协变。
这意味着,尽管您可以执行以下操作:
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
您不能这样做:
if imageUrl.count > 0 {
let eachImage = imageUrl[indexPath.row]
Alamofire.request(eachImage).responseImage(completionHandler: {(response) in
print("answer\(response)")
if let image = response.result.value{
DispatchQueue.main.async {
cell.ImageView.image = image
}
}
})
}
因此Dog dog = new Dog();
Animal animal = dog; // Dog works for Animal, classes are covariant
的类型为List<Dog> dogs = List.of(new Dog());
List<Animal> animals = dogs; // Error, generics are invariant
的不是。但是List<Dog>
的类型为List<Animal>
。
这当然是有道理的,因为Dog
将接受Animal
,而animals
不接受。
在您的第一个代码中,您没有指定要使用的类型,例如:
Cat
因此,让编译器推断类型。它搜索dogs
和compare<Foo>(...)
共有的一种类型,即Thread
。
所以StringBuilder
解析为Object
,很好:
T
在第二个示例中,它不能选择Object
,因为static int compare(Object t1, Object t2) {
return 0;
}
的行为与Object
不同,因为泛型是不变的。因此无法找到匹配的类型,从而发生错误。
答案 1 :(得分:2)
我想补充一点,在第二个代码段中进行简单的更改即可纠正错误:
static <T> void fromArrayToCollection(T[] a, Collection<? extends T> c) { ... }
^
现在,Java编译器将再次推断Object
:
fromArrayToCollection(new Thread[]{}, new ArrayList<StringBuilder>());
此外,您可以显式添加type参数:
Main.<Object>fromArrayToCollection(new Thread[]{}, new ArrayList<StringBuilder>());
^
T => Object
:
static void fromArrayToCollection(Object[] a, Collection<? extends Object> c) { ... }
进一步阅读:Upper Bounded Wildcards。