目录
27、泛型
在没引入泛型之前,传统方法有以下几个问题
-
不能对加入到集合中的数据类型进行约束(不安全)
-
遍历的时候,需要进行类型转换,如果集合中的数据量很大,对效率有影响
如果使用泛型
import java.util.ArrayList;
import java.util.List;
/**
* @author: wentao
* @date: 2022/11/2 17:11
* @version: 1.0
* @description: 泛型体验
*/
public class Generic_ {
public static void main(String[]args){
/*
1.如果编译器发现添加的类型,不符合要求 ,就会报错
2. 在遍历的时候,可以直接取出Integer类型而不是Object
*/
List<Integer> list = new ArrayList();
list.add(1);
list.add(12);
list.add(13);
//假如不小心输错数据了 添加了一个String类型
//编译器会进行检查
// list.add("tom");
for (Integer integer : list) {
System.out.println(integer);
}
}
}
1、概念
-
泛型又称为参数化类型,是jdk5出现的新特性,解决数据类型的安全性问题
-
在类声明或实例化时,只要指定好需要的具体类型即可
-
java泛型可以保证如果程序在编译时没有发出警告,运行的时候就不会产生ClassCastException异常,同时,代码更加简洁、健壮
-
泛型的作用:可以在类声明时通过一个标识表示 类中某个属性的类型,或者是某个方法的返回值类型,或者是参数类型
import java.util.ArrayList;
import java.util.List;
/**
* @author: wentao
* @date: 2022/11/2 19:26
* @version: 1.0
*/
public class Generic2 {
public static void main(String[]args){
Person1 p = new Person1("String");
System.out.println(p.e.getClass());//class java.lang.String
Person1 p1 = new Person1(11);
System.out.println(p1.e.getClass());//class java.lang.Integer
Person1 p2 = new Person1();
System.out.println(p2.e);//null
}
}
class Person1<E> {
E e;
public Person1() {
}
public Person1(E e) {
this.e = e;
}
@Override
public String toString() {
return "Person1{" +
"e=" + e +
'}';
}
}
2、泛型的语法
-
泛型的声明
-
interface 接口 <T>{} 和 class 类 <k,v>{}
-
其中 T,k,v不代表值,而是表示数据类型
-
任意字母都可以 指定一般都是使用T,K,V,E这些
-
-
泛型的实例化
-
List<String> list = new ArrayList<>();
-
Iterator<Customer> iterator = customers.iterator();
-
3.使用细节
自定义泛型类
-
泛型只能是引用数据类型
-
在指定泛型具体类型后,可以传入该类型或者其子类型
-
如果不添加泛型 默认泛型是Object类型
-
普通成员可以使用泛型(属性,方法)
-
使用泛型的数组,不能初始化
-
静态方法不能使用类的泛型
-
泛型类的类型,是在创建对象的时候确定的(因为创建对象的时候,需要指定确定类型)
package com.sofwin.controller;
/**
* @author: wentao
* @date: 2022/11/2 20:36
* @version: 1.0
* @description: 自定义泛型
*/
public class CustomGeneric {
}
//1.Tiger类后有泛型 --所以我们吧tiger就称为自定义泛型类
//2. T R M 是泛型标识符,一般是单个大写字母
//3.泛型的标识符可以有多个
//4.普通成员可以使用泛型(属性 方法)
//5. 使用泛型数组不能初始化
//6.静态方法不能使用泛型
// 也是泛型是实例化的时候指定, 但是出发类的时候 可以调用静态方法
// 这个时候不知道泛型的类型
class Tiger<T,R,M> {
String name;
R r; //属性使用了泛型
T t;
M m;
//泛型的类型是对象实例化的时候指定
//但是这个类中数组 在类加载的时候就初始化了
// 因此当数组实例化的时候 T还不知道什么类型 无法分配空间
//因此只能声明 不能实例化
// T[] ts = new T[8];
T[] ts ;
public Tiger(String name, R r, T t, M m) {
this.name = name;
this.r = r;
this.t = t;
this.m = m;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//返回类型使用泛型
public R getR() {
return r;
}
//方法使用泛型
public void setR(R r) {
this.r = r;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
public M getM() {
return m;
}
public void setM(M m) {
this.m = m;
}
}
自定义泛型接口
-
接口中,静态成员也不能使用泛型
-
泛型接口的类型,在继承接口或者实现接口时确定
-
没有指定类型,默认为Object
/** * @author: wentao * @date: 2022/11/2 20:58 * @version: 1.0 * @description: 自定义泛型接口 */ public class InterfaceGeneric1 { public static void main(String[]args){ } } //没有指定默认是Object class UUTsb implements Usb { @Override public Object get(Object o) { return null; } @Override public void hi(Object o) { } @Override public void run(Object r1, Object r2, Object u1, Object u2) { } } //实现的时候 可以自行指定了 class UUsb implements Usb<Double,Float> { @Override public Float get(Double aDouble) { return null; } @Override public void hi(Float aFloat) { } @Override public void run(Float r1, Float r2, Double u1, Double u2) { } } interface IUsb extends Usb<String ,Integer> { } /* 1. 接口中,静态成员也不能使用翻新 2. 泛型接口的类型,在继承接口或者实现接口时确定 3. 没有指定类型,默认为Object */ interface Usb<U,R> { //接口中属性 默认是 public static final的 public static final int i = 0; // U u; //普通方法在接口中 可以使用泛型 R get(U u); void hi(R r); void run(R r1, R r2, U u1, U u2); //在jdk8中 可以在接口中,使用默认方法 default R method(U u) { return null; } }
自定义泛型方法
基本语法
修饰符 <T,R...> 返回类型 方法名(参数列表)
-
泛型方法,可以定在普通类中,也可以定义的在泛型类中
-
当泛型方法被调用时,类型会确定
-
public void ear(E e ) {} ,修饰符后没有<T,R..> eat方法不是泛型方法,而是使用了泛型
package com.sofwin.controller;
/**
* @author: wentao
* @date: 2022/11/2 21:30
* @version: 1.0
* @description: 泛型方法
*/
public class MethodGeneric1 {
public static void main(String[]args){
Car car = new Car();
// 当泛型方法被调用时,类型会确定
//传入值的类型 编译器就自动确定了
car.fly("str");
car.fly(1);
}
}
//泛型方法 可以定义在普通类中,也可以定义在泛型类中
class Car {
//普通方法
public void run() {}
//泛型方法
//<T,R>就是泛型 是提供给fly使用的
public <T,R> void fly(T t) {
System.out.println(t.getClass());
}
public <T,R> void fly(T t,R r) {
System.out.println(t.getClass());
}
}
class Car2 extends Car {
@Override
public <T, R> void fly(T t) {
}
}
//也可以定义在泛型类
class Fish<T,R> {
public void run () {}
public <W,Q> void ear(W w) {}
}
4.泛型的继承和通配符
-
泛型不具备继承性
List<Object> list = new ArrayList<String>() 是不对的
-
<?>支持任意泛型类型
-
<? extends A> 支持A类以及A类的子类,规定了泛型的上限
-
<? super A> 支持A类以及A类的父类 不限于直接父类,规定了泛型的下限
import org.omg.CORBA.PUBLIC_MEMBER;
import java.util.ArrayList;
import java.util.List;
/**
* @author: wentao
* @date: 2022/11/2 22:16
* @version: 1.0
* @description: 泛型的基础和通配符
*/
public class GenericExtends {
public static void main(String[]args){
Object o = new String("xx");
//1.泛型没有继承性
//这个就不可以了
// List<Object> list = new ArrayList<String>();
//举例说明下面的方法
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
// 1. <?>支持任意泛型类型
printCollection(list1);
printCollection(list2);
printCollection(list3);
printCollection(list4);
printCollection(list5);
// 2. <? extends A> 支持A类以及A类的子类,规定了泛型的上限
// printCollection2(list1); //error Object是A类的父类不是子类
// printCollection2(list2); //error String没有关系
printCollection2(list3); //ok 是AA类
printCollection2(list4); //ok 是AA类的子类
printCollection2(list5);//ok 是AA类的子类(孙子)
// 3. <? super A> 支持A类以及A类的父类 不限于直接父类,规定了泛型的下限
printCollection3(list1); //ok Object是A类的父类
// printCollection3(list2); //error String不是 A类的父类
printCollection3(list3); //AA类是可以的
// printCollection3(list4);//error 是AA类的子类
// printCollection3(list5);//error 是AA类的子类(孙子)
}
// 1. <?>支持任意泛型类型
public static void printCollection(List<?> c) {
for (Object o : c) {
System.out.println(o);
}
}
// 2. <? extends A> 支持A类以及A类的子类,规定了泛型的上限
public static void printCollection2(List<? extends AA> c) {
for (Object o : c) {
System.out.println(o);
}
}
// 3. <? super A> 支持A类以及A类的父类 不限于直接父类,规定了泛型的下限
public static void printCollection3(List<? super AA> c) {
for (Object o : c) {
System.out.println(o);
}
}
}
class AA {
}
class BB extends AA {
}
class CC extends BB {
}