Java中的泛型

泛型

  • 什么是泛型
    • 泛型类
    • 泛型接口
    • 泛型方法
      • 通配符
      • 泛型的上下限
  • 泛型的注意事项
    • 擦除问题
    • 基本数据类型问题

什么是泛型

定义类、接口、方法时,同时声明了一个或者多个类型变量(如:),称为泛型类、泛型接口,泛型方法、它们统称为泛型。

作用:泛型提供了在编译阶段约束所能操作的数据类型,并自动进行检查的能力。这样可以避免强制类型转换,及其可能出现的异常。

泛型的本质:把具体的数据类型作为参数传给类变量。

自定义泛型类
自定义泛型接口
自定义泛型方法

泛型类

Java中的泛型_第1张图片
eg. 模拟ArrayList类

//泛型类
//这里的E,使用A、B、C都是一样的,一般使用E、T、K、V
public class MyArrayList<E> {
	private Object[] arr = new Object[10];
	private int size; //记录当前位置的
	public boolean add(E e) {
		arr[size++] = e;
		return true;
	}
	public E get(int index) {
		return (E) arr[index];
	}
	
}
//泛型类
//这里的E,使用A、B、C都是一样的,一般使用E、T、K、V
public class MyClass<E, T> {
	public void put(E e, T t) {

	}
}
//泛型类3
//在使用时这里的E必须要是继承Animal类的类才可以放进来
//泛型类可以通过extends的方式来限制放入的类型变量
public class MyClass3<E extends Animal> {
	
}

public class Dog extends Animal {
}
//会报错,因为String类型没有继承Animal
MyClass3<String> c3 = new MyClass();
//正确,可以放入Animal本身
MyClass3<Animal> c3 = new MyClass();
//正确,因为Dog继承了animal
MyClass3<Dog> c3 = new MyClass();

泛型接口

Java中的泛型_第2张图片
eg.
场景:系统需要处理学生和老师的数据,需要提供2个功能:
保存对象数据,
根据名称查询数据。

//老师类
public class Teacher {
}
//学生类
public class Student {
}
//泛型接口
public interface Data<T> {
	void add(T t);
	ArrayList<T> getByName(String name);
}

//实现类
public class TeacherData implements Data<Teacher> {
	@Override
	public void add(Teacher teacher) {
	}
	@Override
	public ArrayList<Teacher> getByName(String name) {
		return null;
	}
}

//实现类
public class StudentData implements Data<Student> {
	@Override
	public void add(Student student) {
	}
	@Override
	public ArrayList<Student> getByName(String name) {
		return null;
	}
}

public class Test {
	public static void main(String[] args)
}

泛型方法

在这里插入图片描述
Java中的泛型_第3张图片

通配符

  • 就是“?“,可以在“使用泛型“的时候代表一切类型;E T K V 是在定义泛型的时候使用。

泛型的上下限

  • ? extends Car(上限) ?能接收的必须是Car或Car的子类
  • ? super Car(下限) ?能接收的必须是Car或Car的父类
public static <T> T test(T t) {
	return t;
}
//正确
test(new Dog());
test("java");

eg
需求: 所有的汽车可以一起参加比赛

public class Car {
}

public class BMW extends Car {
}

public class BENZ extends Car {
}

public static void go(ArrayList<Car> cars) {

}

ArrayList<Car> cars = new ArrayList<>();
cars.add(new BMw());
cars.add(new BENZ());
go (cars);

ArrayList<BMW> bmws = new ArrayList<>();
//加入两辆宝马车
bmws.add(new BMW());
bmws.add(new BMW());
//会报错,重点:Car是父类,但ArrayList的Car和ArrayList的BMW是没有关系的
go(bmws);

解决方法

//这样所有类型的ArrayList都可以送进来
public static <T> void go(ArrayList<T> cars) {
}
//仅限定汽车能进来
public static <T extends Car> void go(ArrayList<T> cars) {
}
//ArrayList本身就是泛型,?是通配符,在使用泛型时可以代表一切类型
public static void go(ArrayList<?> cars) {
}
//加入限定
// ? extends Car(上限) 必须是Car或Car的子类
// ? super Car(下限) 必须是Car或Car的父类
//此时可以送入的类型是Car以及Car的子类
public static void go(ArrayList<? extends Car> cars) {
}

泛型的注意事项

擦除问题

  • 泛型是工作在编译阶段的,一旦程序编译成class文件,class文件中就不存在泛型类,这就是泛型擦除

Java中的泛型_第4张图片
class底层中帮你强转类型

基本数据类型问题

  • 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)

引用类型都是Object的子类,而基本类型不是类。

你可能感兴趣的:(Java学习路线,java,开发语言)