[!quote] 泛型 泛型 提供了编译时类型安全检测机制,允许程序员在编译时检测到非法的类型
- 泛型的类型参数只能是包装类【
Integer……】,不能是基本类型【int……】
[!quote] 泛型标记符 泛型的标记符可以自己定义,叫什么都可以
javapublic static <PO, VO> Page\<VO> of(Page\<PO> pagePO) { …… }
EElement 【在集合中使用,因为集合中存放的是元素】TType【Java 类】KKey【键】VValue【值】NNumber【数值类型】
❤ 泛型类,泛型方法,泛型接口
泛型类
- 实现了一个类中不同类型的成员变量
java
class Generic<T> { //泛型类
private T t; // T 可以指代任何类型
public T getT() {return t;}
public void setT(T t) {this.t = t;} //泛型方法
}java
public static void main(String[] args) {
Generic<Integer> gr = new Generic<Integer>();
gr.setT(123);
System.out.println(gr.getT());
Generic<String> grr = new Generic<String>();
grr.setT("Java");
System.out.println(grr.getT());
}
---
123
Java泛型方法
- 实现了同一个方法可以容纳不同的数据类型【方法重载虽然也可以,但代码冗余】
java
public class demo {
public <T> void printArray(T[] inputArray) {
// 输出数组元素
for (T element : inputArray) {
System.out.printf("%s ", element);
}
}
}泛型接口
java
public interface Generic<T> {
void show(T t);
}java
public class GenericImp<T> implements Generic<T> {
public void show(T t) {
System.out.println(t);
}
}java
public class Demo1 {
public static void main(String[] args) {
Generic gr = new GenericImp(); //多态
gr.show(123);
gr.show("Java");
}
}
---
123
Java❤ 有界的类型参数
有时候,我们希望限制可以传递给类型参数的类型的范围【例如,一个操作数字的方法只希望接受 Number ,或者 Number 子类的实例】
java
// 只有实现了 `Comparable<T>` 接口的类型才能作为类型参数。这样,我们就确保了传递给 `findMax` 方法的数组中的对象可以进行比较
public <T extends Comparable<T>> T findMax(T[] array) {
T max = array[0];
for (T element : array) {
if (element.compareTo(max) > 0) {
max = element;
}
}
return max;
}❤ 类型通配符
类型通配符是使用
?代替具体的类型参数,List<?>是所有类似于List<String>,List<Integer>…… 的父类
java
public static void main(String[] args) {
//继承关系:Integer extends Number extends Object
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
//extends Number表示上限是Number类
List<? extends Number> list4 = new ArrayList<Object>(); //报错,不能为Object类
List<? extends Number> list5 = new ArrayList<Number>();
List<? extends Number> list6 = new ArrayList<Integer>();
//super Number表示下限是Number类
List<? super Number> list7 = new ArrayList<Object>();
List<? super Number> list8 = new ArrayList<Number>();
List<? super Number> list9 = new ArrayList<Integer>(); //报错,不能为Integer类
}[!hint]
?与<T>的区别
<T>用于定义泛型,而?用于使用泛型
❤ 创建集合时最好加上泛型
不加入泛型
如果没有设置泛型,集合的默认类型是 Object, 当 l.add 添加的是 int 时,程序不会编译错误,但是在遍历强转时会报错【因为无法将 Integer 类型强转为 String 类型,当然,如果你使用 Object o = it.next() 就可以解决,但是不推荐】
java
public static void main(String[] args) {
List l = new ArrayList();
l.add("你");
l.add("123");
Iterator it = l.iterator();
while (it.hasNext()) {
String s = (String) it.next();
System.out.println(s);
}
}
---
java.lang.ClassCastExceptionjava
public static void main(String[] args) {
List l = new ArrayList();
l.add("你");
l.add(123);
Iterator it = l.iterator();
while (it.hasNext()) {
Object o = it.next();
System.out.print(o);
}
}
---
你123加入泛型
如果设置了泛型,在编译期间
add一个其他类型的数据就会报错
❤ 可变参数
可变参数 可以让我们实现方法形参的可变
java
public class Demo2 {
public static void main(String[] args) {
System.out.println(sum(1, 2, 3));
}
public static int sum(int... a) { //可变参数,这个a其实是个数组
int sum = 0;
for (int i : a) {
sum = sum + i;
}
return sum;
}
}
---
6如果你的方法里既要有固定参数又要有可变参数的话,要把可变参数写在后面,~~因为如果写在前面,编译器会认为你传的参数全部都是可变参数~~。所以一个方法不能有两个可变参数
❤ 补充
类型擦除
[!quote] 类型擦除 类型擦除 是 JVM 在编译时,对泛型的类型进行擦除【
例如,】List<String>会变成List,这意味着在运行时,Java 不知道List里存的是 String 还是其他类型
[!hint] 以下是关于泛型擦除的报错代码:
java// 由于泛型擦除,所以最后两个方法名和参数会完全一样,所以会报错 public static void method(List\<String> list) { System.out.println("HelloWorldStringlist"); } public static void method(List\<Long> list) { System.out.println("HelloWorldLonglist"); }java// T 是泛型,编译器会在编译时把它擦除成 Exception,这样,Java 在运行时就不知道 T 是哪种具体的异常类型 public \<T extends Exception> void handleException() { try { // 可能会抛出异常的代码 } catch (T e) { // 这是非法的 // 处理异常 } }