泛型

56 阅读1分钟

为什么要使用泛型?

  • 使用泛型可以使代码看起来更加清晰,规范
  • 泛型在编译时期可以检测出不符合泛型对应的类型
  • 泛型使我们编程更加简洁,不用强制转换,更加安全

泛型类

public class GenericTest<T> {
    T data;
}

在泛型类中的泛型方法

public class GenericTest<T> {

    T data;

    public <T> T fetch(T t) {
        return null;
    }
}

需要注意的是,泛型类和泛型方法可以指定不同的类型

GenericTest<Integer> genericTest = new GenericTest<>();
String a = genericTest.fetch("a");

类型擦除

泛型在编译之后,就会有类型擦除

public class GenericTest<T> {

    T data;
    
    public GenericTest(T t){
        this.data = t;
    }

    public static void main(String[] args) throws NoSuchFieldException {
        GenericTest<Integer> genericTest = new GenericTest<>(1);
        Field data = genericTest.getClass().getDeclaredField("data");
        System.out.println(data.getType().getName());
    }
}

image.png

泛型通配符

通配符又被分为限定性通配符和非限定行通配符

  • 限定性通配符<? extends 类>
public class GenericTest2<T extends Person> {

    T data;

    public static void main(String[] args) throws NoSuchFieldException {
        GenericTest2<P> test2 = new GenericTest2<>();
        Field data = test2.getClass().getDeclaredField("data");
        System.out.println(data.getType().getName());
    }

}

class Person {

}

class P extends Person{}

image.png

类型擦除为Person

  • 限定通配符<? super 类>,这种通配符不能再类上声明,可以在方法参数上声明
public class GenericTest3 {

    public void test(Collection<? super Dog> t) {
        t.add(new Dog());
        // 编译错误
        t.add(new Animal()); 
    }
}

class Animal {}

class Dog extends Animal{}
  • 非限定通配符,不能进行写操作,不能进行类型相关的操作
public void test2(Collection<?> collection) {
    // 编译错误
    collection.add("a");
}