泛型

HeJin大约 3 分钟Java集合

概述

  • 泛型可以把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。相当于把数据类型作为参数来进行传递。
  • 泛型只能是引用数据类型

使用

既然Object是所有类的父类,为什么不把成员变量设置成Object,这样就可以存储任何类型的值了?

public class Box {
    private Object object;

    public Box() {
    }

    public Box(Object object) {
        this.object = object;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }
}

使用Object是可以的,但是当我们获取到需要的成员变量之后,需要手动进行类型转换,才能调用对应的方法。比较繁琐。而泛型可以解决这个问题,无需强制类型转换。

public class Demo {
    public static void main(String[] args) {
        Box box = new Box(20);

        Object object = box.getObject();
        // 需要手动进行类型转换
        Integer integer = (Integer) object;
        System.out.println(integer.doubleValue());
    }
}

泛型类 & 泛型接口

定义泛型

public class Box<E> {
    private E object;

    public Box() {
    }

    public Box(E object) {
        this.object = object;
    }

    public E getObject() {
        return object;
    }

    public void setObject(E object) {
        this.object = object;
    }
}

使用泛型

public static void main(String[] args) {
    // 创建对象确定了泛型的具体类型
    Box<Integer> box = new Box<>(20);
    Integer integer = box.getObject();

    // 创建对象确定了泛型的具体类型
    Box<String> box1 = new Box<>("hello 泛型");
    String object1 = box1.getObject();

    // 创建对象确定了泛型的具体类型
    Box<Date> box2 = new Box<>(new Date());
    Date object2 = box2.getObject();
}

泛型的确定

  • 创建对象时确定:

    public static void main(String[] args) {
        // 创建对象确定了泛型的具体类型
        Box<Integer> box = new Box<>(20);
        Integer integer = box.getObject();
    }
    
  • 定义子类时确定:

    // 这样SubClass子类就确定为String类型了
    public class SubClass extends Box<String>{
        @Override
        public void test() {
            super.test();
        }
    }
    

    我们在定义子类时也可以选择不确定泛型,让其在创建对象的时候确定:

    public class SubClass<T> extends Box<T>{
        @Override
        public void test(T t) {
            super.test(t);
        }
    }
    

泛型方法

定义泛型

public static <T> T test(T t){
    return t;
}

使用泛型

public static void main(String[] args) {
    Integer integer = test(1);

    String s = test("hello");

    Date date = test(new Date());
}

泛型的确定:调用泛型方法,程序会根据调用自动推导泛型的具体类型。

public static void main(String[] args) {
    // 调用泛型方法是确定类型
    Integer integer = test(1);

    // 调用泛型方法是确定类型
    String s = test("hello");

    // 调用泛型方法是确定类型
    Date date = test(new Date());
}

泛型上限 & 泛型下限

泛型上限:泛型必须是某个类的子类

public static class Person{
    Integer id;
    String name;
}

// 传入的集合泛型必须是Person或者其子类
public static void test(List<? extends Person> t){
    for (Person person : t) {
        System.out.println(person.name) ;
    }
}

泛型下限:泛型必须是某个类的父类

public static class Person{
    Integer id;
    String name;
}

public static void test(List<? super Person> t){
    for (Object o : t) {
        System.out.println(o);
    }
}

注意事项

  • 泛型上限可以在定义泛型类和方法参数上使用。
  • 泛型下限主要在方法参数上使用。