Java 中的協變和逆變是泛型中的一種重要概念,由于操作的復雜性和細節,很多開發者會混淆它們。本文將幫助您了解它們之間的區別。 首先,我們需要理解 Java 的子類型化概念,也就是說:如果 A 是 B 的子類,那么我們可以把 A 的對象直接轉換成 B 的對象。在 Java 中,這個概念稱為子類型多態性。 協變和逆變在子類型多態性中扮演著不同的角色。 協變:在參數類型是求值結果(返回值類型)的子類型的前提下,返回值子類型的方法與原方法是協變的。 逆變:在參數類型是返回值子類型的前提下,方法參數類型的子類型與原方法是逆變的。 接下來,我們來看一些代碼示例,幫助我們更好地理解它們之間的差異。
class Animal {} class Dog extends Animal {} class Kennel在協變和逆變的使用中,我們需要注意以下幾點: - 對于同一參數類型,協變方法是返回類型的子類,而逆變方法是參數類型的子類。 - 在使用通配符進行協變和逆變時,需要注意通配符的上界和下界,以保證代碼的安全性。 - 協變和逆變與泛型的使用方式有關。在 Java 8 之前,Java 并不支持函數式接口,因此需要使用對類進行泛型類型的聲明。在 Java 8 中引入的 Lambda 表達式使得函數式接口成為了可能,這也意味著 Java 8 中接口的泛型類型已經確定,協變和逆變也可以應用于接口。{ T t; public Kennel(T t) { this.t = t; } } // 協變示例 class CovariantDemo { public static void main(String[] args) { Kennel dogKennel = new Kennel<>(new Dog()); Kennel extends Animal>animalKennel = dogKennel; // 這個操作是安全的,因為 Dog 是 Animal 的子類,所以可以將 dogKennel 當做 animalKennel Animal animal = animalKennel.t; // 與之等價于 Dog dog = dogKennel.t; } } // 逆變示例 class ContravariantDemo { public static void main(String[] args) { Kennel animalKennel = new Kennel<>(new Animal()); Kennel super Dog>dogKennel = animalKennel; // 這個操作是安全的,因為 Dog 是 Animal 的子類,所以可以將 animalKennel 當做 dogKennel dogKennel.t = new Dog(); // 與之等價于 animalKennel.t = new Dog(); } }