zoukankan      html  css  js  c++  java
  • 泛型、通配符

    泛型
    回顾泛型类
    泛型类:具有一个或多个泛型变量的类被称之为泛型类。
    public class A<T> {
        private T t;
        public A(T t) {
            this.t = t;
    }
    public T get() {
        return t;
    }
    }


    2 泛型方法
    泛型方法的特点:
    方法的参数中会使用泛型变量;
    方法的返回值中会使用泛型变量。

    public <T> T get(T[] ts) {
      return ts[ts.lengt / 2];
    }
    String[] names ={“zhangSan”, “liSo”, “wangWu”};
    String name = get(names);


      调用泛型方法时无需指定泛型变量,编译器会通过实际参数的类型来识别泛型变量的类型,上例中传递的参数为String[]类型,那么相当于给泛型类型T赋值为String。

    3 继承(实现)泛型类(接口)
    继承泛型类需要为父类的泛型变量赋值!就好比创建泛型类的对象时需要给泛型变量赋值一样。
    // 创建泛型类对象
    List<String> list = new ArrayList<String>();
    // 继承泛型类1:子类也是泛型类
    public class MyList1<T> extends ArrayList<T> {
     …
    }
    // 继承泛型类2:子类不是泛型类
    public class MyList2 extends ArrayList<String> {
      …
    }


    4 通配符
    为了说明通配符的作用,我们先看个例子:
    List<Object> list1 = new ArrayList<String>();
    List<Object> list2 = new ArrayList<Integer>();


    上面的调用都是编译不通过的!
    这说明想写一个即可以打印list1,又可以打印list2的方法是不可能的!

    public static void fun(List<Object> list) {…}
    List<String> list1 = new ArrayList<String>();
    List<Integer> list2 = new ArrayList<Integer>();
    fun(list1);//编译不通过
    fun(list2);//编译不通过


    如果把fun()方法的泛型参数去除,那么就OK了。即不使用泛型!

    public static void fun(List list) {…}//会有一个警告
    List<String> list1 = new ArrayList<String>();
    List<Integer> list2 = new ArrayList<Integer>();
    fun(list1);
    fun(list2);


    上面代码是没有错了,但会有一个警告。警告的原因是你没有使用泛型!Java希望大家都去使用泛型。
    你可能会说,这里TMD根本就不能使用泛型。

    4.1 通配符概述
    通配符就是专门处理这一问题的。

    public static void fun(List<?> list) {…}


    上面代码中的“?”就是一个通配符,它只能在“<>”中使用。造成不能把它从“<>”中拿出来。
    这时你可以向fun()方法传递List<String>、List<Integer>类型的参数了。当传递List<String>类型的参数时,表示给“?”赋值为String;当传递List<Integer>类型的参数给fun()方法时,表示给“?”赋值为Integer。

    4.2 通配符的缺点
      带有通配符的参数不能使用与泛型相关的方法,例如:list.add(“hello”)编译不通过。
    上面的问题是处理了,但通配符也有它的缺点。
    在上面例子中,List<?> list参数中的通配符可以被赋任何值,但同时你也不知道通配符被赋了什么值。
    当你不知道“?”是什么时,会使你不能使用任何与泛型相关的方法。也就是说fun()方法的参数list不能再使用它的与泛型相关的方法了。例如:list.add(“hello”)是错误的,因为List类的add()方法的参数是T类型,而现在你不知道T是什么类型,你怎么去添加String的东西给list呢?如果使用者在调用fun()方法时传递的不是List<String>,而是List<Integer>时,你添加String当然是不可以的。

    当然,还可以调用list的get()方法。就算你不知道“?”是什么类型,但它肯定是Object类型的。所以你可以:Object o = list.get(0);

    4.3 通配符的限制
      通配符只能出现在引用的定义中,而不能出现在创建对象中。例如:new ArrayList<?>(),这是不可以的。ArrayList<?> list = null,这是可以的。

    4.4 带有下边界的通配符
    List<? extends Number> list;
    其中<? extends Number>表示通配符的下边界,即“?”只能被赋值为Number或其子类型。

    public static void fun(List<? extends Number> list) {…}
    fun(new ArrayList<Integer>());//ok
    fun(new ArrayList<Double>());//ok
    fun(new ArrayList<String>());//不ok


    当fun()方法的参数为List<? extends Number>后,说明你只能赋值给“?”Number或Number的子类型。
    虽然这多了一个限制,但也有好处,因为你可以list的get()方法了。就算你不知道“?”是什么类型,但你知道它一定是Number或Number的子类型。所以:Number num = list.get(0)是可以的。
    但是,还是不能调用list.add()方法!

    4.5 带有下边界的通配符
    List<? super Integer> list;
    其中<? super Integer>表示通配符的下边界,即“?”只能被赋值为Integer或其父类型。

    public static void fun(List<? super Integer> list) {…}
    fun(new ArrayList<Integer>());//ok
    fun(new ArrayList<Number>());//ok
    fun(new ArrayList<Object>());//ok
    fun(new ArrayList<String>());//不ok


    这时再去调用list.get()方法还是只能使用Object类型来接收:Object o = list.get(0)。因为你不知道“?”到底是Integer的哪个父类。
    但是你可以调用list.add()方法了,例如:list.add(new Integer(100))是正确的。因为无论“?”是Integer、Number、Object,list.add(new Integer(100))都是正确的。

    4.6 通配符小结
    1. 方法参数带有通配符会更加通用;
    2. 带有通配符类型的对象,被限制了与泛型相关方法的使用;
    3. 下边界通配符:可以使用返回值为泛型变量的方法;
    4. 上边界通配符:可以使用参数为泛型变量的方法。

    5 泛型父类获取子类传递的类型参数
    看一个例子:
    public class A<T> {
    }
    pubilc class B extends A<String> {
    }
    public class C extends A<Integer> {
    }


    如果你需要在A类中得到子类给T赋值的类型,那么可以使用下面的方法:
    public class A<T> {
      public A() {
        ParameterizedType pType = (ParameterizedType)this.getClass().getGenericSuperclass();
        Class clazz = (Class)pType.getActualTypeArguments()[0];
        System.out.println(clazz.getName());
    }
    }

  • 相关阅读:
    input表单元素的默认padding不一致问题
    【转】iOS25彩票 幸运转盘
    微分起源
    转载--微分几何为何必然兴起?
    前缀和?or差分序列?
    noip2014 小结
    2019艾瑞(北京)年度高峰会议-数能驱动新变量
    MSF初体验
    s实现指定时间自动跳转到某个页面
    css实现居中
  • 原文地址:https://www.cnblogs.com/cyf18/p/14315992.html
Copyright © 2011-2022 走看看