# Java:泛型

121 阅读3分钟
  • 用来规范加入容器的元素属性

  • jdk5.0 新增的特性

  • 泛型类型必须是类,不能使用基本数据类型:byte boolean short int double float long char

  • 在实例化集合类的时候可以指明泛型类型

  • 集合类或接口中凡是定义类或接口时,内部结构使用到类的泛型结构的位置,全部使用实例化时定义的泛型类型

  • 如果实例化时,没有指明实例化泛型类型。那就会默认使用 Object 类型。

  • 如何自定义泛型结构

    • 泛型类、泛型接口

      • 模板:

        class Order <T> {
            public int a;
            public String b;
            public T c;
            
            public void setC (T c){
                this.c = c;
            }
            public T getC (){
                return c;
            }
        }
        
      • 如果实例化的时候没有定义泛型类,类的类型将自动默认使用 Object 类。

      • 如果是泛型类,在实例化的时候应该定义类的类型。

      • 如果泛型类有多个参数,应该将多个参数放在尖括号内用逗号隔开 -----> <T , E , K , V>

      • 泛型类的构造器

        class SubOrder<T> extends Order<T> {
            public SubOrder(){}
            // public SubOrder<T>(){} 这样是错误的
        }
        
      • 泛型不同的引用不能相互赋值

        ArrayList<String> arr1 = null;
        ArrayList<Integer> arr2 = null;
        // arr1 = arr2; 这样子是不可以的
        
      • 泛型结构是一个接口或抽象类,不可创建泛型类的对象。因为接口或抽象类的定义使用到了静态,静态不允许是泛型类。

      • 泛型类不能使用基本数据类型,可以使用包装类替换。

      • 静态方法中不能使用类的泛型

        public Order <T>{
            public static void show (T Order){
                // 静态方法中不能使用类的泛型
            }
        } 
        

        因为泛型类的类型实在创建对象的时候才定义。而静态方法实在实例化的时候就存在的。在静态方式出现的时候没办法确认形参类型的存在会报错。

      • 异常不能声明为泛型。异常和泛型基本没有关系

      • 定义泛型数组

        public Order <T>{
            // T[] arr = new T[10]; 错误写法
            T[] arr = (T[]) new Object[10];
        } 
        
      • 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型

        • 父类:

          class Father<T,E>{
          
          }
          
        • 子类不保留父类的泛型:

          没有类型

          class Kid extends Father{
              // 相当于 class Kid extends Father <Object,Object>
          }
          

          具体类型

          class Kid extends Father<String,String>{
          
          }
          
        • 子类保留父类的泛型

          全部保留

          class Kid<T,E> extends Father<T,E>{
          
          }
          class Kid<T,E,K,V> extends Father<T,E>{
              // 不单单是全部保留还新增了 K V 两个泛型
          }
          

          部分保留

          class Kid<E> extends Father<String,E>{
          
          }
          
          class Kid<E,K,V> extends Father<String,E>{
              // 部分保留且新增了 K V 两个泛型
          }
          
    • 泛型方法

      • 模板

        public <E> List<E> copy(E[] arr){
            ArrayList<E> list = new ArrayList<>();
            for(E vallue:arr){
                list.add(value);
            }
            return list;
        }
        

        想创建一个泛型集合类型的方法。必须按照 Collection 这个格式来写方法的类型。

        泛型方法可以声明为静态方法。因为泛型参数在调用的时候类型是确定的。并非在实例化的时候确定的。

  • 泛型在继承方面的体现

    虽然 A 父类,B 是子类。

    但是

    List<A> aList = null;
    List<B> bList = null;
    aList = bList;
    // 是错的
    

    结论: List 和 List 两者之间并不具备继承关系,而是并列关系。

    List<String> list = null;
    ArrayList<String> arrayList = null;
    list = arrayList;
    // 是对的!
    

    结论:List 和 ArrayList 两者之间具备继承关系。