• Java 泛型是 JDK1.5 引入的新特性;
  • 泛型其本质是参数化类型,把类型作为参数传递;
  • 泛型不具备继承性;

常见形式有泛型类、泛型接口、泛型方法。

好处:

  • 提高代码的重用性;
  • 对数据类型进行约束,防止类型转换异常,提高代码的安全性 ;
  • 在遍历时,不需要做类型转换,在集合中的数据量较大时,相较于不使用泛型,有一定的性能提升;

泛型类

语法:类名、类名

注意:

  • 泛型只能使用引用类型
  • 不同的泛型对象不能互相复制

样例代码

  1. public class CollectionTest {
  2. public static void main(String[] args) {
  3. //使用泛型类创建对象
  4. System.out.println("************* String ****************************");
  5. MyGeneric<String> myGeneric = new MyGeneric<String>();
  6. myGeneric.t = "hello";
  7. // myGeneric.t = 123;//无法通过编译
  8. myGeneric.show("大家好");
  9. String str = myGeneric.getT();
  10. System.out.println(str);
  11. System.out.println("************* Integer ****************************");
  12. MyGeneric<Integer> myGeneric_int = new MyGeneric<Integer>();
  13. myGeneric_int.t = 100;
  14. myGeneric_int.show(996);
  15. // myGeneric_int.show("996");//无法通过编译
  16. Integer integer = myGeneric_int.getT();
  17. System.out.println(integer);
  18. // MyGeneric<float>//无法通过编译:泛型只能使用引用类型
  19. // MyGeneric<String> myGeneric_string = new MyGeneric<Integer>();//无法通过编译:不同的泛型对象不能互相复制
  20. }
  21. }
  22. class MyGeneric<T> {
  23. //使用泛型T
  24. //1、创建变量
  25. T t;
  26. //2、作为方法的参数
  27. public void show(T t) {
  28. System.out.println(t);
  29. }
  30. //3、泛型作为方法的返回值
  31. public T getT() {
  32. return t;
  33. }
  34. }

泛型接口

语法:接口名

注意:

  • 不能使用泛型静态常量

样例代码

public class CollectionTest {
    public static void main(String[] args) {
        MyInterfaceImpl impl = new MyInterfaceImpl();
        impl.show("hello");

        MyInterfaceImpl2<Integer> impl2 = new MyInterfaceImpl2<Integer>();
        impl2.show(996);
    }
}

interface MyInterface<T> {
    String name = "静态常量";
//    T t = new T();//无法通过编译

    T show(T t);
}

class MyInterfaceImpl implements MyInterface<String> {
    @Override
    public String show(String str) {
        System.out.println(str);
        return str;
    }
}

class MyInterfaceImpl2<T> implements MyInterface<T> {
    @Override
    public T show(T t) {
        System.out.println(t);
        return t;
    }
}

泛型方法

语法:返回值类型

注意:

样例代码

public class CollectionTest {
    public static void main(String[] args) {
        MyGenericMethod mgm = new MyGenericMethod();
        mgm.show("hello");
        mgm.show(123);
    }
}

class MyGenericMethod {
//    public <T> void show(T t) {
//        System.out.println("泛型方法" + t);
//    }

    public <T> T show(T t) {
        System.out.println("泛型方法:" + t);
        return t;
    }
}

泛型集合

泛型集合是类型安全的集合,它规定了集合元素的类型必须一致。

特点:

  • 编译时即可检查,而非运行时抛出异常。
  • 访问时,不必类型转换(拆箱)。
  • 不同泛型之间引用不能相互赋值,泛型不存在多态。

样例代码

import java.util.ArrayList;
import java.util.Iterator;

public class CollectionTest {
    public static void main(String[] args) {
//        ArrayList<Student> arrayList = new ArrayList<Student>();
        ArrayList<Student> arrayList = new ArrayList<>();

        Student s1 = new Student("张三", 13);
        Student s2 = new Student("李四", 14);
        Student s3 = new Student("王五", 15);
        Student s4 = new Student("李六", 16);

        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s4);

        Iterator<Student> it = arrayList.iterator();
        while (it.hasNext()) {
            Student s = it.next();
            System.out.println(s);
        }
    }
}

class Student {
    String name;
    int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Student studen = (Student) o;
        return this.age == studen.age && this.name.equals(studen.name);
    }

    @Override
    public String toString() {
        return "Studen{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

泛型的继承和通配

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        ArrayList<Object> objList = new ArrayList();
        ArrayList<String> strList = new ArrayList();
        ArrayList<A> aList = new ArrayList();
        ArrayList<B> bList = new ArrayList();
        ArrayList<C> cList = new ArrayList();

        // List<?> list
        printCollection1(list);
        printCollection1(objList);
        printCollection1(strList);
        printCollection1(aList);
        printCollection1(bList);
        printCollection1(cList);

        // List<? extends A> list
        printCollection2(list);
//        printCollection2(objList); // 编译不通过
//        printCollection2(strList); // 编译不通过
        printCollection2(aList);
        printCollection2(bList);
        printCollection2(cList);

        // List<? super A> list
        printCollection3(list);
        printCollection3(objList);
//        printCollection3(strList); // 编译不通过
        printCollection3(aList);
//        printCollection3(bList);  // 编译不通过
//        printCollection3(cList);  // 编译不通过
    }

    // ? 通配符,代表任意泛型类型都可以传进去
    public static void printCollection1(List<?> list) {
        for (Object obj : list) {
            System.out.println(obj);
        }
    }

    // ? extends A 表示上限,表示可以接受 A 或 A 的子类
    public static void printCollection2(List<? extends A> list) {
        for (Object obj : list) {
            System.out.println(obj);
        }
    }

    // ? super A 表示下限,表示可以接受 A 或 A 的父类,不限于直接父类
    public static void printCollection3(List<? super A> list) {
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

class A {

}

class B extends A {

}

class C extends B {

}

问题

T 与 T 有什么差别,使用场景分别是?