[疯狂Java]泛型:泛型构造器、泛型方法的重载问题、泛型数组的问题(应该摒弃)、?下限的典型应用

来源:互联网 发布:泳道图 软件 编辑:程序博客网 时间:2024/05/21 13:56

1. 泛型构造器:

    1) 构造器也是方法,既然有泛型方法,那么构造器也可以定义为泛型方法,那么就变成了泛型构造器;

    2) 由于构造器也是方法,因此反省构造器的定义和普通泛型方法的定义完全相同,例如:public <T> MyClass(T t) { ... }

    3) 使用泛型构造器:

          i. 和使用普通泛型方法一样没区别,一种是显式指定泛型参数,另一种是隐式推断,如果是显式指定则以显式指定的类型参数为准,如果传入的参数的类型和指定的类型实参不符,将会编译报错;

!典型示例:A a = new <String>A("lala"); // 菱形实参还是写在方法名之前

          ii. 这里唯一需要特殊注明的就是,如果构造器是泛型构造器,同时该类也是一个泛型类的情况下应该如何使用泛型构造器:

              a. 因为泛型构造器可以显式指定自己的类型参数(需要用到菱形,放在构造器之前),而泛型类自己的类型实参也需要指定(菱形放在构造器之后),这就同时出现了两个菱形了,这就会有一些小问题,具体用法再这里总结一下;

              b. 这里使用的类是这样定义的:public A<T> { public <E> A(E e) { ... } }

              b. 全指定,例如:A<String> a = new <Integer>A<String>(15); // 所有类型实参全部显式指定,Integer代表E,String代表T

              c. 全隐藏,例如:A<String> a = new A<>(15);   // 可以隐式推断出Integer是E,String是T

              d. 半隐藏,例如:A<String> a = new A<String>(15);  // 还是可以推断出E是Integer,而String是T

              e. 上面的叫做半隐藏T,但是不能半隐藏E,例如:A<String> a = new <Integer>A<>(15);  // 虽然也可以正确推断,但是这种语法不允许!!会直接编译报错!

!!因此这里麻烦的是需要稍微记忆一下,不能半隐藏E

!!平时使用的时候就使用其中一种,推荐是全隐藏,越简洁越好,就是用一种就不会增加记忆负担;


2. 泛型方法的重载问题:

    1) 泛型方法的定义非常灵活,只要形式不同就能形成重载,例如List<T>、List<T extends Xxx>、List<? super Xxx>等都会在重载时当成不一样的类型,因此都能形成重载;

    2) 但是重载泛型方法的时候不能产生歧义,如果产生歧义即使编译没错最后运行时也可能发生错误!

    3) 典型例子:

public static <T> void copy(Collection<T> dest, Collection<? extends T> src);public static <T> void copy(Collection<? super T> dest, Collection<T> src);
!这两个方法形成重载,并且编译没有问题;

!但是如果在运行时这样调用:copy(new ArrayList<Number> ln, new ArrayList<Integer> li);  // 由于上面两个重载版本都符合,因此不知道到底应该调用该哪个方法,因此产生了歧义,随之而来的就是抛出异常!!

!!所以千万不要做这种模棱两可的事情;

3. 泛型数组的问题:这里不解释具体原理了,反正也没人用,所以就杜绝使用泛型数组

    1) Java严格地来说不支持泛型数组,像List<String>[] arr = new List<String>[10]; // 直接编译报错

    2) 其次,用类型参数创建数组也不支持,例如在一个泛型类中,出现这么一句话:new T[15];  // 也会直接编译报错

    3) 因此一定要小心这两种情况,也就是说编程的时候一定要杜绝上述两种情况!


4. ?下限的典型应用:

    1) 首先介绍一个简单的例子:就拿Collections的API(copy方法)来说吧:

public static <T> void copy(Collection<T> dest, Collection<? extends T> src) {for (T ele: src) {dest.add(ele);}}
!没有问题,类型兼容;

!!但如果现在要求该方法返回最后一个被复制的元素呢?可能你会这样改:

public static <T> T copy(Collection<T> dest, Collection<? extends T> src) {T last = null;for (T ele: src) {last = ele;dest.add(ele);}return last;}
!!但是这样又会让src丢失类型信息:Integer last = copy(new ArrayList<Number>(), new ArrayList<Integer>());  // 由于返回值类型就是src的类型上限Number,而Number到Integer并不兼容,因此这里会抛出类型转换异常;

!!除非你对返回值进行强制类型转换,但是既然用了泛型还要那么麻烦地转换类型那不是很吃亏吗?

!!随意这里用?的上限来解决:

public static <T> T copy(Collection<? super T> dest, Collection<T> src) {T last = null;for (T ele: src) {last = ele;dest.add(ele);}return last;}
!!这样src的类型就是确定的类型了,因此last的类型也是确定了类型,就是和src的类型一样!



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 京东e卡绑定错了怎么办 手机换号京东账号绑的银行卡怎么办 京东金条激活失败怎么办 京东买的k3不能激活怎么办 优购手机光黑屏怎么办 优购手机忘记手势密码怎么办 消费卡过期了钱怎么办 超市卡过期了钱怎么办 宜家购物卡的钱怎么办 武商购物卡过期怎么办 丹尼斯卡过期了怎么办 联华ok卡过期了怎么办 汉购通过期了怎么办 天猫退货要检测报告怎么办 京东退货后发票怎么办 京东金融被盗刷怎么办 京东e卡丢了怎么办 京东e卡没有密码怎么办 同一个订单微信付款两次怎么办 京东购物卡掉了怎么办 京东购物卡丢了怎么办 京东快递丢了怎么办 京东e卡支付多了怎么办 京东帐号忘了怎么办 京东白条风控怎么办 我有个破袄…没有衣服怎么办办 轩辕传奇手游灵宠融合错了怎么办 各尧学生不能用怎么办? 山东一卡通商务卡丢了怎么办 和信通过期了怎么办 和信通过期怎么办延期 和信通过期余额怎么办 超市储蓄卡丢了怎么办 提现提到注销卡怎么办 美通卡过期2年了怎么办 物美美通卡丢失怎么办 网上购物电话留错了怎么办 微信斗牛一直输怎么办 微信斗牛输了钱怎么办 微信举报诈骗不成功该怎么办 沙河拿服装太贵怎么办