Java 泛型 提升抽象能力
看完这篇文章,你将获取到 更简单复用的代码 更强的抽象能力 。
基础知识
为什么使用泛型(使用场景)
1.使程序员能够实现通用算法。
2.在编译时进行更强的类型检查,提高代码的安全性。
泛型类
一个泛型类的定义与格式如下:
类名<T1, T2, …, Tn> { /* … */ }
/**
* Generic version of the Box class.
* @param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
//实例化
Box<Integer> integerBox = new Box<>();
其中T是可以是您指定的任何非原始类型:任何类类型、任何接口类型、任何数组类型,甚至是另一个类型变量。
在Java中这些类型命名的约定如下:
最常用的类型参数名称是:
E - 元素(被 Java 集合框架广泛使用)
K - 键
N - 数字
T - 类型
V - 值
S、U、V 等 - 第 2、第 3、第 4 种类型
泛型接口
//泛型接口
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
泛型方法
静态泛型方法 非静态泛型方法
public class Util {
//静态泛型方法
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
//实现泛型接口
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
//非静态泛型方法
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
//实例化
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);
OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");
Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.compare(p1, p2);
好了,以上就是泛型的基础使用方法。下面进入日常使用
有界类型参数
什么叫有界类型参数,就是将泛型定为有界的,分为上界和下界,来限制参数类型,增强类型检查和使用有界类型的特性;
上界
格式如下 T extends 具体的类型或接口
extends在一般意义上用于表示“继承”(如在类中)或“实现”(如在接口中)。
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
//这里泛型方法 就用了上界 表示U 是Number类及其子类
public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
// error: 这里就编译不通过,因为是String。 体现泛型作用之一的:增强类型检查
integerBox.inspect("some text");
}
}
//泛型类 使用上界
public class NaturalNumber<T extends Integer> {
private T n;
public NaturalNumber(T n) { this.n = n; }
public boolean isEven() {
//因为定义了上界,所以我们就可以使用上界Integer的特性:intValue方法
return n.intValue() % 2 == 0;
}
}
下界
格式如下 ? super A
下限通配符将未知类型限制为特定类型或该类型的超类型。
假设您要编写一个将Integer对象放入列表的方法。为了最大限度地提高灵活性,您希望该方法适用于List<Integer>、List<Number>和List<Object> — 任何可以保存Integer值的东西。
要编写上的列表工程方法整和的超类型整数,如整型,数量和 对象,此时就需要使用下界。
因为List<Integer>只匹配一个Integer类型的列表,而List<? super Integer匹配一个Integer超类型的任何类型的列表。
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i); }
}
}
实际运用
我们使用枚举的时候,有时经常要根据枚举的code值来获取整个枚举,从而获取这个枚举其他属性。
一般我们都是在这个枚举中遍历枚举,然后根据code比较返回整个枚举。若有多个枚举就需要重复写类似逻辑。这里我们用泛型来抽象一下写法,减少代码量不需要每个枚举都写一遍
/**
* @className: EnumBase
* @description: 枚举接口抽象
* @author: xk
* @date: 2021/6/8 10:34
**/
public interface EnumBase <T>{
T getCode();
String getMessage();
/**
* xk:根据code值判断是否在该枚举中
*
* @param enums
* @param code
* @return
*/
static <T> boolean isExistBycode(EnumBase[] enums, T code) {
if (code == null) {
return false;
}
for (EnumBase e : enums) {
if (code.equals(e.getCode())) {
return true;
}
}
return false;
}
/**
* @param: enums 实现EnumBase的枚举值集合
* @param: code 枚举code
* @description: 通过枚举code 获取对应的枚举实体
* @return: T 枚举实体
* @author: xk
* @date: 2021/6/29 20:36
*/
static <T extends EnumBase, R> T getEnumByCode(T[] enums, R code) {
for (T e : enums) {
if (Objects.equals(code, e.getCode())) {
return e;
}
}
return null;
}
}
enum StepInfoStatusEnum implements EnumBase<Integer> {
init(0, "未开始"),
success(1, "成功"),
fail(2, "失败")
Integer code
String message
StepInfoStatusEnum(Integer code, String message) {
this.code = code
this.message = message
}
@Override
Integer getCode() {
return this.code
}
@Override
String getMessage() {
return this.message
}
}
//最后使用
StepInfoStatusEnum stepInfoStatusEnum = EnumBase.getEnumByCode(StepInfoStatusEnum.values(),0);
最后附上Oracle官方教程地址:https://docs.oracle.com/javase/tutorial/java/generics/index.html
多总结,多学习