泛型
1. 认识泛型
定义类、接口、方法时,同时声明了一个或多个类型变量(如:),称为泛型类、泛型接口、泛型方法、它们统称为泛型。
2. 泛型类
public class Test {
public static void main(String[] args) {
MyArrayList<String> list = new MyArrayList<>();
System.out.println(list.add("Jack")); // true
System.out.println(list.get(0)); // Jack
}
}
// 自定义一个泛型类,去模拟 ArrayList
class MyArrayList<E> { // 如果不想规范地写,其实E也可以写成其他字母
private Object[] arr = new Object[10]; // 容器,用来装东西
private int size; // 记录当前装了多少个
public boolean add(E content) {
arr[size++] = content;
return true;
}
public E get(int index) {
return (E) arr[index];
}
}
public class Test {
public static void main(String[] args) {
MyClass<String, String> obj = new MyClass<>();
obj.put("只能是String类型", "只能是String类型");
// Others<String> obj1 = new Others<>(); // 报错
Others<MyClass> obj2 = new Others<>(); // 正常
System.out.println(obj2.age); // 输出结果:0
}
}
class MyClass<E, T> {
public void put(E e, T t) {
}
}
// 要求 E 的类型是继承 MyClass 或者 E 的类型是 MyClass
class Others<E extends MyClass> {
public int age;
}
3. 泛型接口
- 注意:类型变量建议用大写的英文字母,常用的有:E、T、K、V 等
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
}
}
class Student {
}
class Teacher {
}
// 泛型接口
interface Data<E> {
void add(E obj);
ArrayList<E> getByName(String name);
}
// 实现类
class StudentData implements Data<Student> {
@Override
public void add(Student obj) {
}
@Override
public ArrayList<Student> getByName(String name) {
return null;
}
}
// 实现类
class TeacherData implements Data<Teacher> {
@Override
public void add(Teacher obj) {
}
@Override
public ArrayList<Teacher> getByName(String name) {
return null;
}
}
4. 泛型方法
案例一
public class Test {
public static void main(String[] args) {
System.out.println(get(10)); // 10
System.out.println(get("Java")); // Java
System.out.println(get(new A())); // 对象的内存地址: login.A@3b07d329
}
// 泛型方法
public static <T> T get(T name) {
return (T) name;
}
// 泛型方法
public static <E> void run(E index) {
}
}
class A {
}
案例二
通配符:就是" ? ",可以在"使用泛型"的时候代表一切类型;E T K V 是在定义泛型的时候使用
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
// 需求:实现所有的汽车都能一起参加比赛
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());
go(bmws);
ArrayList<BENZ> benzs = new ArrayList<>();
benzs.add(new BENZ());
benzs.add(new BENZ());
go(benzs);
ArrayList<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
// go(dogs); // 报错
}
// <T>是没有限制数据类型的泛型,如果我们加一个限制条件,不要让狗类进来,可以这样写:<T extends Cars>,完整代码如下一行所示
public static <T extends Car> void go(ArrayList<T> allCars) {
}
// 知识扩展:
// ? 是通配符,在使用泛型的时候可以代表一切类型" ? extends Car "【上限】 " ? super Car "【下限】
// public static void go1(ArrayList<? extends Car> allCars) {}
// public static void go2(ArrayList<? super Car> allCars) {}
}
class Car {
}
class BMW extends Car {
}
class BENZ extends Car {
}
class Dog {
}
5. 注意事项
- 泛型是工作在编译阶段的,一旦程序编译成 class 文件,class 文件中就不存在泛型了,这就是泛型擦除。
- 泛型不支持基本数据类型,只能支持对象类型(引用数据类型)
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
// ArrayList<int> list1 = new ArrayList<>(); // 报错
ArrayList<Integer> list2 = new ArrayList<>(); // 正常
}
}