Skip to content

Commit

Permalink
2023-8-24
Browse files Browse the repository at this point in the history
  • Loading branch information
depers committed Aug 24, 2023
1 parent 0e06507 commit 40dcbed
Show file tree
Hide file tree
Showing 14 changed files with 250 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static void main(String[] args) {
/**
* 为什么Java的数组是支持泛型的:
* 一是Java数组是1.0版本提出来的,那个时候还没有泛型。
* 而是Java设计者希望能够对数组进行通用的处理,如果数组不支持协变的话,很多方法就得为每一种类型编写逻辑了,如下所示
* 二是Java设计者希望能够对数组进行通用的处理,如果数组不支持协变的话,很多方法就得为每一种类型编写逻辑了,如下所示
* @param array
*/
public static void process(Object[] array) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package cn.bravedawn.generic.wildcards;

public class HsqDog extends Dog{

// 哈士奇
}
24 changes: 24 additions & 0 deletions 2.JavaTrain/src/main/java/cn/bravedawn/generic/wildcards/Pair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cn.bravedawn.generic.wildcards;

public class Pair<T> { // public class Pair<T extends java.lang.Object> extends java.lang.Object

/**
* Java的类型擦除,可以使用 javap -v xx.class去查看
*/

private T first; // private Object first;
private T last; // private Object last;

public Pair(T first, T last) { // public Pair(Object first, Object last)
this.first = first;
this.last = last;
}

public T getFirst() { // public Object getFirst()
return first;
}

public T getLast() { // public Object getLast()
return last;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package cn.bravedawn.generic.wildcards;

public class SmyDog extends Dog{

// 萨摩耶
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cn.bravedawn.generic.wildcards.lowerbounds;

import cn.bravedawn.generic.wildcards.Dog;
import cn.bravedawn.generic.wildcards.HsqDog;
import cn.bravedawn.generic.wildcards.SmyDog;

import java.util.ArrayList;
import java.util.List;

public class LowerBoundsExample {

/**
* 我们现在有一个场景,将src列表的元素复制到dest列表中
* @param dest 目标列表
* @param src 源列表
*/
public static void copyHappyDog(List<Dog> dest, List<Dog> src) {
for (Dog dog : src) {
dest.add(dog);
}
}


/**
* 如果将Dog子类的集合传入到src中就会编译失败
*/
public static void main(String[] args) {

copyHappyDog(new ArrayList<Dog>(), new ArrayList<Dog>());
//copyHappyDog(new ArrayList<Dog>(), new ArrayList<HsqDog>()); // 编译失败
//copyHappyDog(new ArrayList<Dog>(), new ArrayList<SmyDog>()); // 编译失败
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cn.bravedawn.generic.wildcards.lowerbounds;

import cn.bravedawn.generic.wildcards.Animal;
import cn.bravedawn.generic.wildcards.Dog;
import cn.bravedawn.generic.wildcards.HsqDog;
import cn.bravedawn.generic.wildcards.SmyDog;

import java.util.ArrayList;
import java.util.List;

public class LowerBoundsExample2 {

/**
* 我们现在有一个场景,将src列表的元素复制到dest列表中
* @param dest 目标列表
* @param src 源列表
*/
public static void copyHappyDog(List<Dog> dest, List<? extends Dog> src) {
for (Dog dog : src) {
dest.add(dog);
}
}


/**
* copyHappyDog()方法的src参数使用上边界符进行限定,Dog子类的列表都可以接受
* 但是如果参数dest传递Dog父类的集合就会编译失败
*/
public static void main(String[] args) {

copyHappyDog(new ArrayList<Dog>(), new ArrayList<Dog>());
copyHappyDog(new ArrayList<Dog>(), new ArrayList<HsqDog>());
copyHappyDog(new ArrayList<Dog>(), new ArrayList<SmyDog>());
//copyHappyDog(new ArrayList<Animal>(), new ArrayList<SmyDog>()); // 编译失败
//copyHappyDog(new ArrayList<Object>(), new ArrayList<SmyDog>()); // 编译失败
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cn.bravedawn.generic.wildcards.lowerbounds;

import cn.bravedawn.generic.wildcards.Animal;
import cn.bravedawn.generic.wildcards.Dog;
import cn.bravedawn.generic.wildcards.HsqDog;
import cn.bravedawn.generic.wildcards.SmyDog;

import java.util.ArrayList;
import java.util.List;

public class LowerBoundsExample3 {

/**
* 我们现在有一个场景,将src列表的元素复制到dest列表中
* @param dest 目标列表
* @param src 源列表
*/
public static void copyHappyDog(List<? super Dog> dest, List<? extends Dog> src) {
for (Dog dog : src) {
dest.add(dog);
}
}


/**
* copyHappyDog()方法的dest参数使用 下边界符 进行限定,Dog父类的列表都可以接受
*/
public static void main(String[] args) {

copyHappyDog(new ArrayList<Dog>(), new ArrayList<Dog>());
copyHappyDog(new ArrayList<Dog>(), new ArrayList<HsqDog>());
copyHappyDog(new ArrayList<Dog>(), new ArrayList<SmyDog>());
copyHappyDog(new ArrayList<Animal>(), new ArrayList<SmyDog>());
copyHappyDog(new ArrayList<Object>(), new ArrayList<SmyDog>());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cn.bravedawn.generic.wildcards.lowerbounds;

import cn.bravedawn.generic.wildcards.*;

import java.util.ArrayList;
import java.util.List;

public class LowerBoundsExample4 {

/**
* 1.泛型的下界描述符是支持添加元素的,因为他没有类型转换失败的风险
* 2.泛型的下界描述符修饰的集合只能添加指定类型或是指定类型的子类,添加其他类型是会编译失败的,切记不要将接收泛型类和添加泛型类弄混了
* 3.大家就会发现,协变和逆变正好相反,上界发生协变只读不写,下界发生逆变只写不读。所以两者的使用场景也就出来了,正如copyHappyDog()方法
* 1)如果我对泛型只读不写时,使用协变,下界描述符。
* 2)如果我对泛型只写不读时,使用逆变,上界描述符。
* 3)如果我又想写又想读,那你不需要使用逆变和协变,你需要使用准确的泛型类型。
* 4)泛型的协变和逆变一般只使用在方法上,声明形参来接收调用者传递的实参,之前的代码中使用协变和逆变修饰变量和类是为了方便演示。
*/


/**
* 我们现在有一个场景,将src列表的元素复制到dest列表中
* @param dest 目标列表
* @param src 源列表
*/
public static void copyHappyDog(List<? super Dog> dest, List<? extends Dog> src) {
for (Dog dog : src) {
dest.add(dog);
}
}

public static void func(List<? super Dog> list) {
list.add(new Dog());
list.add(new HsqDog());
list.add(new SmyDog());

//list.add(new Animal()); // 添加其他元素就会编译错误
//list.add(new Cat()); // 编译错误

// 使用下界描述符声明的对象,只能使用Object类型获取对象
Object object = list.get(0);

//Animal animal = list.get(0); // 编译错误
//Dog dog = list.get(0); // 编译错误
}


public static void main(String[] args) {
func(new ArrayList<Dog>());
func(new ArrayList<Animal>());
func(new ArrayList<Object>());

//func(new ArrayList<SmyDog>()); // 传入子类的泛型类就会编译错误
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @author : depers
* @program : JavaTrain
* @description:
* @date : Created in 2023/8/22 19:51
*/
package cn.bravedawn.generic.wildcards.lowerbounds;


/**
* 泛型下界描述符的相关代码
*/
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cn.bravedawn.generic.wildcards;

/**
*
* 这个包主要介绍了泛型的协变和逆变
* 还有就是PECS原则,关于PECS原则,大家可以参考java.util.Collections#copy(java.util.List, java.util.List)方法
*/
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
package cn.bravedawn.generic.wildcards.upperbounds;

import cn.bravedawn.generic.wildcards.Animal;
import cn.bravedawn.generic.wildcards.Cat;
import cn.bravedawn.generic.wildcards.Dog;

public class Node <T extends Animal> {
public class Node <T extends Animal> { // public class Node<T extends Animal>


/**
* extends关键字的用途
* 1.如果extends关键字用于类上,则他可以对成员变量的泛型类型进行校验
* 2.成员变量可以访问父类的方法
*/


private T previous;
private T next;
private final T animal; // private final Animal animal;

public static void main(String[] args) {
Node<Animal> animalNode;
Node<Dog> dogNode;
Node<Cat> catNode;

// 可以对成员变量的泛型类型进行校验
// Node<String> stringNode; // 编译错误
}


public Node(T animal) { // public void Node(Animal animal)
this.animal = animal;
}

// 成员变量可以访问泛型父类的方法。
public void process() {
animal.eat();
animal.sleep();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public static void main(String[] args) {


public static void process(List<? extends Animal> list) {
Animal animal = list.get(0);
System.out.println("...");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cn.bravedawn.generic.wildcards.upperbounds;

import cn.bravedawn.generic.wildcards.Animal;
import cn.bravedawn.generic.wildcards.Dog;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -20,10 +21,10 @@ public class UpperBoundsExample4 {

public static void main(String[] args) {
Collection<? extends Animal> animals = new ArrayList<>();
Animal animal = new Animal();
Dog dog = new Dog();

//animals.add(new Animal()); // 编译错误
animals.contains(animal);
animals.remove(animal);
//animals.add(dog); // 编译错误
animals.contains(dog);
animals.remove(dog);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package cn.bravedawn.generic.wildcards.upperbounds;

/**
* 泛型的上界描述符
*
* 泛型的上界描述符的相关知识点
*/

0 comments on commit 40dcbed

Please sign in to comment.