第8章 范型程序设计
范型要解决的问题就是让编写的代码可以被很多不同的类型所重用。例如List<String>
,就是一个简单的范型的使用。
下面就列举一个简单的范型的代码例子。
package paradigmtrain;
import java.time.LocalDate;
/**
* ParadigmTrain1.java
* Description: 范型练习类
*
* @author Peng Shiquan
* @date 2020/5/15
*/
public class ParadigmTrain1 {
public static void main(String[] args) {
LocalDate[] dates = {LocalDate.of(1996, 12, 9), LocalDate.of(1997, 5, 15), LocalDate.of(1998, 5, 15)};
Pair<LocalDate> result = minmax(dates);
System.err.println(result.getFirst());
System.err.println(result.getSecond());
/**
* 这里可以通过参数的形式来推断出范型的类型,所以不需要输入范型的类型参数
*/
new Pair<>("haha", "hehe");
}
/**
* Description: 输入的参数必须要实现Comparable。
*
* @param a
* @return paradigmtrain.Pair<T>
* @Author: Peng Shiquan
* @Date: 2020/5/15
*/
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];
int aLength = a.length;
for (int i = 0; i < aLength; i++) {
/**
* 比较大小,通过compareTo方法
*/
if (min.compareTo(a[i]) > 0) min = a[i];
if (max.compareTo(a[i]) < 0) max = a[i];
}
return new Pair<>(min, max);
}
}
/**
* ParadigmTrain1.java
* Description: 范型类
*
* @author Peng Shiquan
* @date 2020/5/15
*/
class Pair<T> {
private T first;
private T second;
public Pair() {
first = null;
second = null;
}
public Pair(T first, T second) {
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
}
-
可以通过对范型参数添加
extends
,来限制范型参数的类型。如下:public static <T extends Comparable & Serializable> Pair<T> minmax(T[] a) {
-
范型的原理。
注意:
-
为了解决类型擦除于多态的冲突,需要生成一个桥方法。(比较复杂,了解即可)
-
关于范型的事实。
-
范型的约束和局限
-
不能用基本类型实例化类型参数。类型擦除后,变为Object,但是Object不能存储基本类型的值。
-
运行时类型查询只适用于原始类型。即这个代码是错误的。
if(a instanceof Pair<String>)
(无法判断)。 -
不能创建参数化类型的数组。数组会记住它的元素类型,如果试图存储其他类型的元素会报异常。
-
不能构造范型数组。
-
不能实例化类型变量。
-
范型类的静态上下文中类型变量无效。
-
不能抛出或捕获范型类的实例。
-
-
范型类型的继承规则。Employee是Manager的父类,但是
Pair<Employee>
不是Pair<Manager>
的父类。 -
通配符类型中,允许类型参数变化。
看书是有点枯燥的,尤其这种难读的东西,下面写个例子,把上面的东西串联起来。
package paradigmtrain; /** * ParadigmTrain2.java * Description: 综合练习,把范型知识点串联起来 * * @author Peng Shiquan * @date 2020/7/22 */ public class ParadigmTrain2 { public static void main(String[] args) { Manager ceo = new Manager("zhangshan", 8000, 24); Manager cfo = new Manager("lisi", 9000, 25); Pair<Manager> managerPair = new Pair<>(ceo, cfo); printBuddies(managerPair); ceo.setMoney(10000); cfo.setMoney(20000); Manager[] managers = {ceo, cfo}; Pair<Manager> managerPair1 = new Pair<>(); minMaxBonus(managers, managerPair1); System.err.println("minMaxBonus:" + managerPair1.getFirst().getName() + "==" + managerPair1 .getSecond().getName()); maxMinBonus(managers, managerPair1); System.err.println("minMaxBonus:" + managerPair1.getFirst().getName() + "==" + managerPair1 .getSecond().getName()); } /** * Description: 通配符类型 * * @param pair * @return void * @Author: Peng Shiquan * @Date: 2020/7/22 */ public static void printBuddies(Pair<? extends Employee> pair) { Employee employee = pair.getFirst(); Employee employee1 = pair.getSecond(); System.err.println("printBuddies" + employee.getName() + "====" + employee1.getName() + "====="); } /** * Description: 通配符的超类型限定,限定父类 * * @param managers * @param pair * @return void * @Author: Peng Shiquan * @Date: 2020/7/22 */ public static void minMaxBonus(Manager[] managers, Pair<? super Manager> pair) { if (managers.length == 0) { return; } Manager min = managers[0]; Manager max = managers[1]; for (int i = 0; i < managers.length; i++) { if (min.getMoney() > managers[i].getMoney()) min = managers[i]; if (max.getMoney() < managers[i].getMoney()) max = managers[i]; } pair.setFirst(min); pair.setSecond(max); } public static void maxMinBonus(Manager[] managers, Pair<? super Manager> pair) { minMaxBonus(managers, pair); PairAlg.swapHelper(pair); } } class PairAlg { /** * Description: 无限定通配符 * * @param pair * @return boolean * @Author: Peng Shiquan * @Date: 2020/7/22 */ public static boolean hasNull(Pair<?> pair) { return pair.getFirst() == null || pair.getSecond() == null; } public static void swap(Pair<?> pair) { } public static <T> void swapHelper(Pair<T> tPair) { T t = tPair.getFirst(); tPair.setFirst(tPair.getSecond()); tPair.setSecond(t); } }