Java泛型

泛型的概念

所谓泛型,就是允许在定义类、接口时通过一个表示表示类中某个属性的类型或是某个方法的返回值及参数类型;这个类型参数将在使用时确定

为什么要使用泛型:解决元素存储的安全性问题,好比商品、药品标签,不会弄错;解决获取数据元素时,需要类型强制转换的问题,好比不用每回拿商品、药品都要辨别

泛型的应用

  • 在集合中使用泛型(最经常使用)

    在实例化集合时,可以指明具体的泛型类型;指明完以后,在集合类或接口中凡是定义类或接口时,内部结构使用到类的泛型的位置,都指定为实例化的泛型类型

    注意:泛型的类型时类,不是基本数据类型

     // 以ArrayList为例
     ArrayList<Integer> list = new ArrayList<Integer>();
     list.add(88);
     // 编译时,就会进行类型检查,保障数据的安全
     // list.add("Tom") 编译报错
     
     // 方式一:增加for循环
     for(Interger score : list){
      // 避免了强转操作
      int Stuscore = score;
      System.out.println(Stuscore);
     }
     
     // 方式二:迭代器
     Iterator<Integer> iterator = list.iterator();
     while(iterator.hasNext()){
      int stuScore = iterator.next();
      System.out.println(Stuscore);
     }
     // 以HashMap为例
     Map<String, Integetr> map = new HashMap<String, Integer>();
     map.put("age", 18);
     
     // 泛型的嵌套
     Set<Map.Entry<String, Integer>, Integer> entry = map.entrySet();
     Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
     
     while(iterator.hasNext()){
      Map.Entry<String, Intrger> e= iterator.next();
      String key = e.getKey();
      Integer value = e.getValue();
      System.out.println(key + "----" + value);
     }
  • 在自定义类中使用泛型

     public class Time<H,M,S>{
         private H hour;
         private M minute;
         private S second;
         
         public H getHour(){
             return hour;
        }
         
         public M geMinute
             return minute;
        }
     
         public H getSecond
             return second;
        }
     
      public void setHour(H hour) {
        this.hour = hour;
        }
     
      public void setMinuter(M minute){
        this.minutenute
        }
     
      public void setSecond(S second){
        this.secondcond
        }
     }
     public class Test {
         public static void main(String[] args) {
             // 如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型
             // 要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型
             // Time time = new Time();
             // time.setHour(10.0f);
             // time.setMinute("10")
             // time.setSecond(10)
             
             // 建议:实例化时指明类的泛型
             Time<String,Integer,Float> time = new Time<>();
             time.setHour("十点");
             time.setMinute(10);
             time.setSecond(10.0f);
             System.out.println("现在的时间是"+time.getHour()+":"+time.getMinute()+":"+time.getSecond());
        }
     }
  • 在接口中使用泛型

     public interface MyInterface<T> {
         public T getValue();
     }

    实现泛型接口有两种方式:

    • 实现类在定义时继续使用泛型标识

       public class MyInterfaceImpl<T> implements MyInterface  {
       
           private T obj;
       
           public MyInterfaceImpl(T obj) {
               this.obj = obj;
          }
       
           @Override
           public T getValue() {
               return this.obj;
          }
       }
    • 实现类在定义时直接给出具体的数据类型

       package com.southwind.demo;
       
       public class MyInterfaceImpl2 implements MyInterface<String> {
       
           private String obj;
       
           public MyInterfaceImpl2(String obj) {
               this.obj = obj;
          }
       
           @Override
           public String getValue() {
               return this.obj;
          }
       }
     public class Test {
         
         public static void main(String[] args) {
             
             MyInterfaceImpl myInterface = new MyInterfaceImpl<String>("接口");
             String val = (String) myInterface.getValue();
     
             MyInterfaceImpl2 myInterface1 = new MyInterfaceImpl2("接口");
             val = myInterface1.getValue();
        }
     }
  • 在方法中使用泛型

    在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系;换句话说,泛型方法所属的类是不是泛型类都没有关系

     public <E> List<E> copyFromArrayToList(E[] arr){
      ArrayList<E> list = new ArrayList<>();
     
      for(E e : arr){
      list.add(e);
      }
      return list;
     }
     @Test
     public void test(){
      Order<String> order = new Order<>();
     
      Integer[] arr = new Integer[]{1, 2, 3, 4};
      // 泛型方法在调用时,指明泛型参数的类型
      // 泛型方法,可以声明为静态的;原因:泛型参数是在调用方法时确定的,并非在实例化类时确定的
      List<Integer> list = order.copyFromArrayToList(arr);
     
      System.out.println(list);
     }

泛型在继承上的体现

  • 泛型类的注意点

    • 泛型类可能有多个参数,此时应将多个参数一起放在尖括号内;比如:<E1, E2, E3>

    • 泛型类的构造器:public GenreicClass(){}

    • 实例化后,操作原来泛型位置的结构必须与指定的泛型类型一致

    • 泛型不同的引用不能相互赋值

    • 泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价于Object

    • 如果泛型结构是一个接口或者抽象类,则不可创建泛型类的对象

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

    • 异常类不能声明为泛型类

    • 不能使用new E[]; 但是可以 E[] elements = (E[])new Object[capacity];

    • 父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型

  • 子类继承父类

    1. 情况一:子类在继承带泛型的父类时,指明了泛型类型

       public class SubOrder extends Order<String>{
       }
       public class GenericTest {
       
           public static void main(String[] args) {
       
               // 由于子类在继承带泛型的父类时,指明了泛型类型;则实例化子类对象时,不再需要指明泛型
               SubOrder sub1 = new SubOrder();
               sub1.setOrderT("aaa");
          }
       }
    2. 情况二:子类在继承带泛型的父类时,没有指明泛型类型

       public class SubOrder<T> extends Order<T>{
       }
       public class GenericTest {
       
           public static void main(String[] args) {
       
               // 由于子类在继承带泛型的父类时,没有指明泛型类型;则实例化子类对象时,需要指明泛型
               SubOrder<String> sub2 = new SubOrder<>();
               sub2.setOrderT("aaa");
          }
       }
  • 子父类关系

     虽然类A是类B的父类,但是G<A>和G<B>二者不具备子父类关系,二者是并列关系,它们的共同父类是G<?>;

    类A是类B的父类,A<G>是B<G>的父类

泛型通配符

    • 普通通配符:?

       @Test
       public void test(){
        List<Object> list1 = null;
        List<String> list2 = null;
       
        List<?> list = null;
       
        list = list1;
        list = list2;
       
        print(list1);
        print(list2);
       }
       
       public void print(List<?> list){
        Iterator<?> iterator = list.iterator();
        while(iterator.hasNext()){
        Object obj = iterator.next();
        }
       }
       
       // 注意:
       // 添加(写入):对于List<?>,除了添加null之外,不能向其内部添加数据;
       // 获取(读取):允许读取数据,读取的数据类型为Object
    • 有限制条件的通配符:?extends Object; ?super Object

      泛型的上限:? extends A:G<? extends A> 可以作为G<A>和G<B>的子类,其中B是A的子类

      泛型的下限:? super A:G<? super A> 可以作为G<A>和G<B>的父类,其中B是A的父类



posted @ 2021-05-06 00:39  离渊灬  阅读(76)  评论(0)    收藏  举报