泛型


对于泛型,如果我们拿Object去写的话,并不通用,就比如你写一个栈,拿到返回值必须强转(从Object强转到你想要的类型),如果有多个返回值,那就得强转多次,所以这个方法行不通,于是引入了泛型:

一、泛型的意义

1、可以对类型进行自动检查 =====> 检查并不是替换(编译期间进行检查,放入元素的时候检查)
2、可以自动对类型进行转换 =====> 转换也不是替换(拿出元素的时候自动转换)

T:类型占位符 表示该类是一个泛型类

二、泛型类型怎么编译的?

类型的擦除机制: 擦除到Object(向上擦除),在编译器编译期间把泛型全部擦除为Object类型

三、泛型的上界:(泛型没有下界)

class GenericAlg<T extends Comparable<T>> {
    public T findMaxVal(T[] array) {  //找到数组中的最大值
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}
 <T extends Comparable<T>>

这样的话指定擦除到Comparable就停止了,否则的话,擦除到Object,但Object并没有实现Comparable接口,于是便不能比较了;上界就是规定了擦除的位置;

四、通配符?:

Integer         ArrayList<Integer>
Number           ArrayList<Number>
Object           ArrayList<Object> 

这些不构成继承关系,类之间有继承关系,但他们的泛型类型之间并不构成继承关系

也有擦除机制,也是擦除到Object
不知道传入参数类型,通通接收

//写一个通用的算法:打印集合ArrayList内的所有元素
class GenericAlg3 {
    public static <T> void printList1(ArrayList<T> list) {
        for (T obj : list) {
            System.out.print(obj + " ");
        }
        System.out.println();
    }
    //?  :通配符  擦除机制 ==== 》Object
    public static void printList(ArrayList<?> list) {
        for (Object obj : list) {
            System.out.print(obj + " ");
        }
        System.out.println();
    }
}

通配符的应用:
因为基类实现的接口,派生类用的时候没必要在实现一次。
通配符的上界、下界;
(上界一般用不到,上界主要用来写入,一般用作库的开发(如DK源码))
(下界主要用来读取)


    /**
     * ArrayList<? extends T> 上界  主要用来写入
     * @param list
     * @param <T>
     * @return
     */
    public static <T extends Comparable<T>> T findMaxVal(ArrayList<? extends T> list) {
        T max = list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }
    
    /**
     * 通配符的下界:找到是不是有T的基类实现了Comparable接口
     * 主要用来读取
     */
      public static <T extends Comparable<? super T>> T findMaxVal2(ArrayList<T> list) {
        T max = list.get(0);
        for (int i = 0; i < list.size(); i++) {
            if(max.compareTo(list.get(i)) < 0) {
                max = list.get(i);
            }
        }
        return max;
    }

五、注意:

1、泛型数组不能new,可以 this.elem = (T[])new Object[size];不能 new T[]
2、不能new泛型类型的对象 不能 T o = new T();
3、不能new泛型类型的对象数组 (如果能那就写Object就可以了,然后就又回去了)
4、不能用简单类型作为泛型类型的参数,
5、一定要加泛型类型的参数,否则就是Object了,又回去了
6、在静态方法中,类不能使用泛型类型的参数,因为静态方法不依赖于对象,如果不依赖于对象,就不知道这个T是什么类型,那编译的时候就没法(静态方法中T:会通过实参的类型推演出泛型类型;也可以传参数的时候添上类型)

class GenericAlg2 {
    /**
     * 泛型方法
     * @param array
     * @param <T>
     * @return
     */
    public static <T extends Comparable<T>> T findMaxVal(T[] array) {
        T max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(array[i].compareTo(max) > 0) {
                max = array[i];
            }
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值