网站建设的杂志,工程公司起名大全字库,国际著名平面设计作品,北京公司网站制作要多少钱目录 Java 泛型核心知识总结泛型什么是泛型#xff1f;有什么用#xff1f;泛型有哪些限制#xff1f;为什么#xff1f;项目中哪里用到了泛型#xff1f;什么是类型擦除#xff1f;什么是桥方法#xff1f; 通配符什么是通配符#xff1f;有什么作用#xff1f;通配符… 目录 Java 泛型核心知识总结泛型什么是泛型有什么用泛型有哪些限制为什么项目中哪里用到了泛型什么是类型擦除什么是桥方法 通配符什么是通配符有什么作用通配符 ? 和常用的泛型 T 之间有什么区别?介绍一下常用的通配符 学习参考 Java 泛型核心知识总结
泛型
什么是泛型有什么用
Java 泛型(Generics)是 JDK 5 中引入的一个新特性它提供了一种类型安全的编程机制可以在编译时检查类型错误避免了在运行时出现类型转换异常的情况。它可以使程序员在编写代码时指定类型参数从而使得代码更加灵活和可重用。
比如 ArrayListPersion persons new ArrayListPersion() 这行代码就指明了该 ArrayList 对象只能传入 Persion 对象如果传入其他类型的对象就会报错。
类型参数 T 是一种占位符类型用于表示实际的类型。 一般在哪定义 Java 泛型可以用于类、接口和方法的定义中。
三种使用方式泛型类、泛型接口、泛型方法。 使用泛型有什么好处 简单来说使用泛型参数可以增强代码的可读性以及稳定性。
使用泛型可以带来许多好处比如
类型安全Java 泛型可以在编译时检查类型错误避免了在运行时出现类型转换异常的情况。代码重用泛型可以使代码更加通用和模块化可以重用在不同的场景中。更好的性能泛型可以避免不必要的类型转换和装箱操作从而提高代码的性能。 泛型的实现方式 泛型主要通过以下两种方式来实现参数化类型和通配符类型。
泛型有哪些限制为什么
泛型参数 T 不能是基本类型例如 int因为实际类型是 ObjectObject 类型无法持有基本类型。无法取得带泛型的 Class。getClass()无法判断带泛型的类型。因为擦除后为 object 类型object 无法使用 进行比较。不能实例化泛型参数的数组。因为擦除后为 object 后无法进行类型判断。不能实现两个不同泛型参数的同一接口擦除后多个父类的桥方法将冲突。不能使用 static 修饰泛型变量。泛型数组的限制Java 泛型数组的创建和使用受到一些限制例如无法创建泛型数组、无法向泛型数组中添加元素等。
项目中哪里用到了泛型
比如
自定义接口通用返回结果类 CommonResultT 通过参数 T 可根据具体的返回类型动态指定结果的数据类型。定义 Excel 处理类 ExcelUtilT 用于动态指定 Excel 导出的数据类型。构建集合工具类参考 Collections 中的 sort, binarySearch 方法。
什么是类型擦除
类型擦除是指在 Java 编译器将泛型代码编译成字节码时会将泛型类型擦除替换为实际的类型或者 Object 类型从而使得泛型类型在运行时不存在。
注意是【实际的类型】或者 【Object】类型。 为什么要擦除 这是因为 Java 虚拟机并不支持泛型所以需要在编译期对泛型进行擦除将泛型代码转换为普通的 Java 类型。
比如
泛型类型没有定义类型参数的限定类型的情况
class MyListT { ... }对于上面的 MyListT 类实际上编译器会将其擦除成如下形式
class MyList {...
}在运行时我们无法获取泛型类型的类型参数例如 无法获取 MyListString 和 MyListInteger 的类型参数它们都被擦除为 MyList 类型。
什么是桥方法
桥方法Bridge Method是 Java 泛型类型擦除机制的一种补偿措施。它是指在泛型类或泛型接口中由编译器自动生成的一个方法用于在类型擦除后保持多态性。
具体说明
在 Java 泛型中由于类型擦除机制的存在导致在某些情况下泛型类型的继承关系会被破坏。
例如下面的代码
public class MyListT {...public void add(T element) {...}
}假设我们定义了一个子类
public class MyStringList extends MyListString {...
}由于类型擦除机制的存在MyStringList 类实际上是继承自 MyList 类的原始类型而不是继承自 MyListString 类型。
因此如果我们在 MyStringList 类中定义一个重写 add() 方法的话会出现编译错误
public class MyStringList extends MyListString {...Overridepublic void add(String element) {...}
}这是因为 Java 编译器会将 MyStringList 类中的 add() 方法擦除成如下形式
public void add(Object element) {...
}这个方法的参数类型是 Object与 MyListString 中的 add 方法的参数类型不同因此编译器会报错。 为了解决这个问题Java 编译器会在 MyStringList 类中自动生成一个桥方法用于在类型擦除后保持多态性 public class MyStringList extends MyListString {...Overridepublic void add(Object element) {add((String) element);}public void add(String element) {...}
}在上面的代码中编译器会自动生成一个桥方法 add(Object element)它会调用原始方法 add(String element)从而保持多态性。
通配符
什么是通配符有什么作用
泛型类型是固定的某些场景下使用起来不太灵活于是通配符就来了
通配符可以允许类型参数变化用来解决泛型无法协变的问题。
举个例子:
// 限制类型为 Person 的子类
? extends Person
// 限制类型为 Manager 的父类3
? super Manager通配符 ? 和常用的泛型 T 之间有什么区别?
T 可以用于声明变量或常量而 ? 不行。T 一般用于声明泛型类或方法通配符 ? 一般用于泛型方法的调用代码和形参。T 在编译期会被擦除为限定实际类型或 object通配符用于捕获具体类型。 擦除为限定实际类型是什么意思 1、如果泛型类型定义了类型参数的限定类型例如
class MyListT extends Number {private T[] elements;public void add(T element) { ... }public T get(int index) { ... }
}那么在编译时编译器会将类型参数 T 擦除为其限定类型 Number例如
class MyList {private Number[] elements;public void add(Number element) { ... }public Number get(int index) { ... }
}因此在运行时无法获取泛型类型的类型参数 T而只能获取其限定类型 Number。
2、如果泛型类型没有定义类型参数的限定类型例如
class MyListT {private T[] elements;public void add(T element) { ... }public T get(int index) { ... }
}那么在编译时编译器会将类型参数 T 擦除为 Object 类型例如
class MyList {private Object[] elements;public void add(Object element) { ... }public Object get(int index) { ... }
}因此在运行时无法获取泛型类型的类型参数 T而只能获取其擦除后的类型 Object。
介绍一下常用的通配符
常用的通配符有三种
? extends T 上边界通配符 extends表示该泛型必须是 T 的子类包括 T 本身用于限定泛型的上界。? super Integer下边界通配符 super表示该泛型必须是 T 的父类包括 T 本身用于限定泛型的下界。?无限定通配符 ?表示任意类型用于表示不确定的类型参数。无限定通配符 ? 很少使用可以用 T 替换同时它是所有 T 类型的父类。
学习参考
一文搞懂泛型https://www.cnblogs.com/XiiX/p/14719568.html