Java基础:泛型及其通配符

泛型:就是参数化类型

 

泛型介绍

泛型类:具有一个或多个类型变量的类

class A<T>{

}

在创建泛型类实例的时候需要给其类型变量赋值:

A <String> a=new A<String>();

注意:为了兼容旧版本,在建立实例时,可以不给类型变量赋值,但是会有警告!

泛型方法:具有一个或多个类型变量的方法,称之为泛型方法。

class A<T>{

         public T fun(T t1){}

}

fun()方法不是泛型方法,只是泛型类中的一个方法

public <T> T fun(T t1){}:是泛型方法。

泛型方法和泛型类没有必然关系,泛型方法不一定需要在泛型类中。

class A<T> {
  private T bean;//泛型可在成员变量上使用
  public T fun(T t) {}//泛型可以在类中的方法上(返回值和参数类型)使用!

  public void fun2() {//泛型还可以在局部变量的引用类型上使用
    T b = ...
    new T();//不行的!
  }
}

泛型和数组比较理解
     *      (1)存放类型任意时
     *      Object[] a=new Object[10];//存放任意类型,但是长度固定
     *      List b=new ArrayList();//也可以存放任意类型,长度任意
     *      (2)存放类型指定时
     *      Object[]a=new String[10];//只能存放String类型
     *      a[0]=new Integer(100);//会报存储异常 ArrayStoreException
     *
     *      List<Object> b=new ArrayList<String>();//泛型两边的类型必须相同,否则编译不通过
     *      因为泛型仅仅是在编译时起作用,编译后会擦除
     *      所以如果上面通过了编译,编译擦除后,下面的添加就不会报错!
     *      b.add(new Integer(100));

需要注意的是:Java中的泛型是“假”的。只是在编译的时候有效,编译后会进行泛型擦除

 

继承泛型类

class AA extends A<String> {}

        AA不是泛型类,其父类是泛型类

       这里子类不是泛型类,需要给父类传递类型变量。

class AA1<E> extends A<E> {}

      AA1和其父类都是泛型类

      子类是泛型类:可以给父类传类型常量,也可以传递类型变量

 

泛型的通配符

 

通配符使用的场景

  方法的形参

 

通配符的优点

使方法更加通用

 

通配符分类

  • 无界通配:?
  • 子类限定:? extends Object
  • 父类限定:? super Integer

通配符缺点

  •   使变量使用上不再方便
  •   无界:参数和返回值为泛型的方法,不能使用!
  •   子类:参数为泛型的方法不能使用
  •   父类:返回值为泛型的方法不能使用

 

比较通配符

通过对java中的数列中方法:addAll的两种泛型通配符的使用对比
boolean addAll(Collection<E> c)

List<Number> numList = new ArrayList<Number>();
List<Integer> intList = new ArrayList<Integer>();
numList.addAll(intList);//addAll(Collection<Number> c), 传递的是List<Integer>

上面赋值会报错,在泛型中,赋值两边的泛型类必须相同,添加进去相当于进行了 List<Number>=List<Integer>,无法通过编译。


boolean addAll(Collection<? extends E> c)

List<Number> numList = new ArrayList<Number>();
List<Integer> intList = new ArrayList<Integer>();
numList.addAll(intList);//addAll(Collection<? extends Number> c), 传递的是List<Integer>

继承泛型通配符可以将子类或其自身添加进来。

 

通过反射得到泛型类类型

public class Demo2 {

    @Test
    public void func1(){

        AA aa=new AA();
        AA2 aa2=new AA2();

    }
}

class A<T>{
    public A(){
        /**
         * 1、得到目标对象
         * 2、获得目标对象的Type
         * 3、获得目标对象的ParameterizeType
         * 4、获得目标对象参数类型
         */
        Class clazz=this.getClass();
        //获得父类的Type,并转化成ParameterizedType类型(A<T>)
        ParameterizedType type= (ParameterizedType) clazz.getGenericSuperclass();

        //得到父类的真实参数类型数组
        Type[] types = type.getActualTypeArguments();

        Class c= (Class) types[0];
        System.out.println(c.getName());
    }
}

class AA extends A<Integer>{

}

class AA2 extends A<String>{

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值