文章目录

  • 第一节 泛型入门
  • 第二节 自定义泛型设计
  • 第三节 泛型类型限定
  • 第四节 泛型实现的本质和约束
  • 第五节 java类型协变和逆变
  • 总结


第一节 泛型入门

泛型是啥?泛型是JDK1.5推出的特性,指的是编写的代码可以被很多不同类型的对象重用。

用来解决啥问题?编程中,我们希望可以参数化类型,避免类型转换,实现代码复用性。

举个例子:通过指定类型(<>中的内容)

java泛型类判断 java 泛型类型_编程语言

泛型分类:

  • 泛型类:ArrayList、HashSet、HashMap等
  • 泛型方法:Collections.binarySearch、Arrays.sort等
  • 泛型接口:List、Iterator等

第二节 自定义泛型设计

希望自己能够设计泛型类,泛型方法、泛型接口。

泛型类定义:

  • 具有泛型变量的类。在类名后面用代表引用类型。
  • 多个字母表示多个引用类型,如<T,U>等。
  • 引用类型可以修饰成员变量、局部变量、参数和返回值。

泛型类使用:

interval<Integer> v1 = new Interval<Integer>(1,2);

java泛型类判断 java 泛型类型_java泛型类判断_02

泛型方法:

  • 具有泛型参数的方法,可以存在与普通类泛型类中。
  • 在修饰符后,返回类型前
  • 调用泛型方法时,引用类型时需要一致,否则容易出错。
public class ArrayUtil {
	public static void main(String[] args) {
		String s1 = Test.<String>getMiddle("abc","def","ghi");
		Integer i1 = Test.getMiddle(1,2,3);
		//null is ok
		String s2 = Test.getMiddle("abc",null,null);
		Number i2 = Test.getMiddle(1,2.5f,2.5f);
		
		System.out.println(s1);   //def
		System.out.println(i1);   //2
		System.out.println(s2);   //null
		System.out.println(i2);   //2.5
	}
}

class Test{
	public static <T> T getMiddle(T... a) {
		return a[a.length/2];
	}
}

泛型接口:

  • 和泛型类相似,在类名后加
  • T用来指定方法返回值和参数
  • 实现接口时,指定类型,实现类不要求是泛型类,可以把其当做普通类。
  • 类型是可以相互嵌套的

java泛型类判断 java 泛型类型_java_03

类型嵌套实例:

java泛型类判断 java 泛型类型_编程语言_04

第三节 泛型类型限定

泛型的限定:希望在某些场合下,对泛型的类型进行限定,要求传入的类型必须有啥方法、实现啥接口。

java泛型类判断 java 泛型类型_java泛型类判断_05

package chapter8;
import java.time.*;

public class PareTest2 {

	public static void main(String[] args) {
		LocalDate[] birthdays = {
				LocalDate.of(1906, 12, 9),
				LocalDate.of(1815, 12, 10),
				LocalDate.of(1910, 12, 3),
				LocalDate.of(1910, 6, 23),
		};
		Pair<LocalDate> mm = ArrayAlg2.minmax(birthdays);
		System.out.println(mm.getFirst());
		System.out.println(mm.getSecond());
	}

}

class ArrayAlg2{
	public static <T extends Comparable> Pair<T> minmax(T[] a){
		if(a == null || a.length == 0) return null;
		T min = a[0];
		T max = a[0];
		for(int i = 0; i < a.length; i++) {
			if(min.compareTo(a[i]) > 0) min = a[i];
			if(max.compareTo(a[i]) < 0) max = a[i];
		}
		return new Pair<>(min, max);
	}
}

泛型类之间的继承:

  • Pair<S>Pair<T>没有任何关系,无论S和T之间是啥关系。
  • 泛型类可以扩展或者实现其他类,如ArrayList<T>实现List<T>

上面两句话是啥意思呢?意思是泛型类之间的继承与T无关,与类本身的继承相关联。

泛型中通配符的使用。

java泛型类判断 java 泛型类型_泛型_06

java泛型类判断 java 泛型类型_泛型_07

通配符限定与类型变量限定十分类似,但是,可以指定一个超类型限定。

java泛型类判断 java 泛型类型_java_08

java泛型类判断 java 泛型类型_编程语言_09

直观讲:带有超类型限定的通配符运行写入一个泛型对象,带有子类型限定的通配符允许读入一个泛型对象。

java泛型类判断 java 泛型类型_java_10

java泛型类判断 java 泛型类型_java泛型类判断_11

下面这段代码就能够体现这个原则。

package chapter8;

import inherit.Employee;
import inherit.Manager;

public class PairTest3 {

	public static void main(String[] args) {
		var ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15);
		var cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15);
		var buddies = new Pair<Manager>(ceo, cfo);
		
		ceo.setBonus(1000000);
		cfo.setBonus(500000);
		Manager[] managers = {ceo, cfo};
		
		var result = new Pair<Employee>();
		minmaxBonus(managers, result);
		System.out.println("first: " + result.getFirst().getName() + " , second: " + result.getSecond().getName());
		maxminBonus(managers, result);
		System.out.println("first: " + result.getFirst().getName() + " , second: " + result.getSecond().getName());
		
	}
	
	public static void printBuddies(Pair<? extends Employee> p) {
		Employee first = p.getFirst();
		Employee second = p.getSecond();
		System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
	}
	
	public static void minmaxBonus(Manager[] a, Pair<? super Manager> result) {
		if(a.length == 0) return;
		Manager min = a[0];
		Manager max = a[0];
		for(int i = 0; i < a.length; i++) {
			if(min.getBonus() > a[i].getBonus()) min = a[i];
			if(max.getBonus() < a[i].getBonus()) max = a[i];
		}
		result.setFirst(min);
		result.setSecond(max);
	}
	
	public static void maxminBonus(Manager[] a, Pair<? super Manager> result) {
		minmaxBonus(a, result);
		PairAlg3.swap(result);
	}
}

class PairAlg3{
	public static boolean hasNulls(Pair<?> p) {
		return p.getFirst() == null || p.getSecond() == null;
	}
	
	public static void swap(Pair<?> p) {
		swapHelper(p);
	}
	
	public static <T> void swapHelper(Pair<T> p) {
		T t = p.getFirst();
		p.setFirst(p.getSecond());
		p.setSecond(t);
	}
}

第四节 泛型实现的本质和约束

这个类型擦除才能够很好的解释泛型的特点与本质。

java泛型类判断 java 泛型类型_java_12

java泛型类判断 java 泛型类型_java_13

java泛型类判断 java 泛型类型_接口_14

java泛型类判断 java 泛型类型_接口_15

java泛型类判断 java 泛型类型_编程语言_16

java泛型类判断 java 泛型类型_接口_17

第五节 java类型协变和逆变

java泛型类判断 java 泛型类型_编程语言_18

java泛型类判断 java 泛型类型_java泛型类判断_19

java泛型类判断 java 泛型类型_java_20

总结

坚持走下去。