一、优点

编译时检查添加元素类型,安全
减少类型转换,效率
没有警告

  1. // 泛型
  2. public class Generic1 {
  3. public static void main(String[] args) {
  4. // <Dog> 表示arrayList只能放Dog类型
  5. ArrayList<Dog> arrayList = new ArrayList<Dog>();
  6. arrayList.add(new Dog("aa",14));
  7. arrayList.add(new Dog("dd",2));
  8. // 遍历时可以直接用Dog 不用Object转Dog
  9. for (Dog dog:arrayList) {
  10. System.out.println(dog.getName()+" "+dog.getAge());
  11. }
  12. }
  13. }
  14. class Dog {
  15. private String name;
  16. private int age;
  17. public Dog(String name, int age) {
  18. this.name = name;
  19. this.age = age;
  20. }
  21. public String getName() {
  22. return name;
  23. }
  24. public void setName(String name) {
  25. this.name = name;
  26. }
  27. public int getAge() {
  28. return age;
  29. }
  30. public void setAge(int age) {
  31. this.age = age;
  32. }
  33. }

二、简介

泛型,又称参数化类型,表示数据类型的数据类型
作用:在类声明时通过一个标识表示类中某个属性的类型,或者时某个方法的返回值的类型,或是参数类型

  1. public class Generic2 {
  2. public static void main(String[] args) {
  3. Person<String> person = new Person<String>("xcv"); // 相当于下面所有E都是String
  4. person.f();
  5. }
  6. }
  7. class Person<E> {
  8. E s; // 属性的数据类型在创建Person的时候指定,在编译期间就确定E是什么类型
  9. public Person(E s) { // E作为参数类型
  10. this.s = s;
  11. }
  12. public E f(){
  13. System.out.println(s.getClass()); // class java.lang.String
  14. return s; // E作为返回类型
  15. }
  16. }

三、语法

3. 1 泛型的声明

interface 接口 {} 和 class 类 {}
T,K,V 不代表值,是表示类型
可以使用任意字母,常用T

3.2 泛型的实例化

要在类名后面指定类型参数的值(类型)
List strList = new ArrayList();
Iterator iterator = customers.iterator();

  1. public class Generic3 {
  2. // 用泛型的方式给HashSet放入3个对象
  3. public static void main(String[] args) {
  4. HashSet<Student> students = new HashSet<Student>();
  5. students.add(new Student("A",14));
  6. students.add(new Student("B",15));
  7. students.add(new Student("C",16));
  8. // 遍历
  9. for (Student s:students) {
  10. System.out.println(s);
  11. }
  12. // 用泛型给HashMap添加3个对象
  13. HashMap<String,Student> hashMap = new HashMap<String,Student>();
  14. hashMap.put("A",new Student("AA", 28));
  15. hashMap.put("V",new Student("VV", 29));
  16. hashMap.put("C",new Student("CC", 27));
  17. // 迭代器 EntrySet
  18. Set<Map.Entry<String,Student>> set = hashMap.entrySet();
  19. Iterator<Map.Entry<String,Student>> iterator = set.iterator();
  20. while (iterator.hasNext()) {
  21. Map.Entry<String, Student> next = iterator.next();
  22. System.out.println(next.getKey()+" "+next.getValue());
  23. }
  24. }
  25. }
  26. class Student {
  27. private String name;
  28. private int age;
  29. public Student(String name, int age) {
  30. this.name = name;
  31. this.age = age;
  32. }
  33. public String getName() {
  34. return name;
  35. }
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39. public int getAge() {
  40. return age;
  41. }
  42. public void setAge(int age) {
  43. this.age = age;
  44. }
  45. @Override
  46. public String toString() {
  47. return "Student{" +
  48. "name='" + name + '\'' +
  49. ", age=" + age +
  50. '}';
  51. }
  52. }

3.3 注意事项

  1. interface List{},public class HashSet{}..

T,E只能是引用类型

  1. 在给泛型指定具体类型后,可以传入该类型或其子类类型
  2. 泛型使用形式

List list1 = new ArrayList();
List list2 = new ArrayList<>();

  1. 不给泛型指定类型,默认是Object ```java public class Generic { public static void main(String[] args) {

    1. // 1. 给泛型指向数据类型是引用类型,不能是基本数据类型
    2. List<Integer> integers = new ArrayList<Integer>();
    3. // List<int> ints = new ArrayList<int>(); 不能是int这类基本数据类型
    4. // 2. 泛型指定类型可以是该类型,也可以是该类型的子类型
    5. Pig<A> aPig = new Pig<A>(new A()); // E指定了A类型
    6. Pig<A> bPig = new Pig<A>(new B());
    7. // 3. 使用形式
    8. ArrayList<Integer> integers1 = new ArrayList<Integer>();
    9. List<Integer> integers2 = new ArrayList<Integer>();
    10. // 简写 编译器推断类型
    11. ArrayList<Integer> list = new ArrayList<>();
    12. List<Integer> list1 = new ArrayList<>();
  1. List list2 = new ArrayList(); // 4. 这样写泛型默认是Object
  2. }

} class A{} class B extends A{} class Pig { E e;

  1. public Pig(E e) {
  2. this.e = e;
  3. }

}

  1. <a name="hEPMZ"></a>
  2. ## 四、自定义
  3. <a name="zYvMt"></a>
  4. ### 4.1 自定义泛型类
  5. class 类名<T,R,...>{<br />成员<br />}
  6. 1. 普通成员可以使用泛型(属性、方法)
  7. 1. 使用泛型的数组不能初始化
  8. 1. 静态方法中不能使用类的泛型
  9. 1. 泛型类的类型,实在创建对象时确定的
  10. 1. 在创建类型时没有指定类型默认为Object
  11. ```java
  12. public class CustomGeneric_ {
  13. public static void main(String[] args) {
  14. }
  15. }
  16. // Tiger后面有泛型,Tiger称为自定义泛型类
  17. // 泛型标识符可以有福哦个
  18. // 普通成员可以使用泛型(属性和方法)
  19. // 使用泛型数组不能初始化
  20. // 静态属性和方法不能使用泛型,因为在类加载,没创建对象时就使用,不能确定类型
  21. class Tiger<T,R,M>{
  22. String name;
  23. T t;
  24. M m;
  25. R r;
  26. // T[] ts = new T[10]; 不能确定T的类型,不知道需要多大的空间
  27. T[] ts;
  28. public Tiger(String name, T t, M m, R r) {
  29. this.name = name;
  30. this.t = t;
  31. this.m = m;
  32. this.r = r;
  33. }
  34. public String getName() {
  35. return name;
  36. }
  37. public void setName(String name) {
  38. this.name = name;
  39. }
  40. public T getT() {
  41. return t;
  42. }
  43. public void setT(T t) {
  44. this.t = t;
  45. }
  46. public M getM() {
  47. return m;
  48. }
  49. public void setM(M m) {
  50. this.m = m;
  51. }
  52. public R getR() {
  53. return r;
  54. }
  55. public void setR(R r) {
  56. this.r = r;
  57. }
  58. }

4.2 自定义泛型接口

interface 接口名{}

  1. 接口中,静态成员不能使用泛型
  2. 泛型接口的类型在继承接口或者实现接口时确定
  3. 没有指定类型,默认为Object ```java public class CustomInterfaceGeneric { public static void main(String[] args) {

    } } interface IUsb{ R get(U u); void hi(R r); void run(R r1,R r2,U u1,U u2); default R method(U u){

    1. return null;

    } } // 继承接口时,指定泛型接口类型 interface IA extends IUsb{

} // 实现IA接口时,IA继承IUsb接口,指定了U为String ,R为Double,String替换了U,Double替换了R class AA implements IA { @Override public Double get(String s) { return null; }

  1. @Override
  2. public void hi(Double aDouble) {
  3. }
  4. @Override
  5. public void run(Double r1, Double r2, String u1, String u2) {
  6. }
  7. @Override
  8. public Double method(String s) {
  9. return IA.super.method(s);
  10. }

} // 实现接口时,指定泛型的接口类型 class BB implements IUsb{ @Override public Float get(Integer integer) { return null; }

  1. @Override
  2. public void hi(Float aFloat) {
  3. }
  4. @Override
  5. public void run(Float r1, Float r2, Integer u1, Integer u2) {
  6. }
  7. @Override
  8. public Float method(Integer integer) {
  9. return IUsb.super.method(integer);
  10. }

}

  1. <a name="WJTWk"></a>
  2. ### 4.3 自定义泛型方法
  3. 修饰符 <T,R...> 返回类型 方法名(参数列表){}
  4. 1. 泛型方法,可以定义在普通类中,也可以定义在泛型类中
  5. 1. 当泛型方法被调用时,类型会确定
  6. ```java
  7. public class CustomMethodGeneric {
  8. public static void main(String[] args) {
  9. Car car = new Car();
  10. car.fly("a",111); // 调用方法时,传入参数 编译器就会确定类型
  11. }
  12. }
  13. // 泛型方法可以定义在普通类中,也可以定义在泛型类中
  14. class Car{ // 普通类
  15. // <T,R>是泛型,提供给fly使用
  16. public <T,R> void fly(T t,R r){ // 泛型方法
  17. }
  18. }
  19. class Fish<T,R>{ // 泛型类
  20. public void run(){
  21. }
  22. public <U,M> void eat(){
  23. }
  24. //hi()方法不是泛型方法,只是使用了泛型
  25. public void hi(T t){
  26. }
  27. // 泛型方法可以使用类声明的泛型,也可以使用自己声明的泛型
  28. public <K> void hello(R r,K k){ // K是泛型方法自己声明的泛型
  29. }
  30. }

五、继承和通配符

  1. 泛型不具备继承性
  2. <?> 支持任意泛型类型
  3. <? extends A> 支持A类以及A类的子类,确定上限
  4. <? super A> 支持A类以及A类的父类,不限于直接父类,确定下限 ```java public class GenericExtends { public static void main(String[] args) {

    1. Object o = new String("xx");
    2. // List<Object> list = new ArrayList<String>();错的,泛型不具备继承性
    3. List<Object> list = new ArrayList<>();
    4. List<String> list1 = new ArrayList<>();
    5. List<AAA> list2 = new ArrayList<>();
    6. List<BBB> list3 = new ArrayList<>();
    7. List<CCC> list4 = new ArrayList<>();
    8. print1(list);
    9. print1(list1);
    10. print1(list2);
    11. print1(list3);
    12. print1(list4);
    13. // List<? extends AAA> c 可以接受AAA或AAA的子类
    14. // print2(list); x
    15. // print2(list1); x
    16. print2(list2);
    17. print2(list3);
    18. print2(list4);
    19. // List<? extends AAA> c 可以接受AAA或AAA的子类
    20. print3(list);
    21. // print3(list1); x
    22. print3(list2);
    23. // print3(list3); x
    24. // print3(list4); x

    }

    @Test public static void print1(List<?> c){

    1. for(Object object : c){ // 通配符 取出时就是Object
    2. System.out.println(object);
    3. }

    }

    // ? extends AAA 表示上限 可以接受AAA或AAA的子类 public static void print2(List<? extends AAA> c){

    1. for(Object object : c) {
    2. System.out.println(object);
    3. }

    }

    // ? super AAA 表示下限 可以接受AAA或AAA的父类,不限于直接父类 public static void print3(List<? super AAA> c){

    1. for(Object object : c) {
    2. System.out.println(object);
    3. }

    } } class AAA{

} class BBB extends AAA{

} class CCC extends BBB{

} ```