问:请说说下面代码片段中注释行执行结果和原因?

  1. DynamicArray<Integer> ints = new DynamicArray<>();

  2. DynamicArray<? extends Number> numbers = ints;

  3. Integer a = 200;

  4. numbers.add(a);        //这三行add现象?

  5. numbers.add((Number)a);

  6. numbers.add((Object)a);

  7. public void copyTo(DynamicArray<? super E> dest){

  8.    for(int i=0; i<size; i++){

  9.        dest.add(get(i));    //这行add现象?

  10.    }

  11. }

答:上面代码段注释行执行情况解释如下。

三个 add 方法都是非法的,无论是 Integer,还是 Number 或 Object,编译器都会报错。因为 ? 表示类型安全无知,? extends Number 表示是 Number 的某个子类型,但不知道具体子类型, 如果允许写入,Java 就无法确保类型安全性,所以直接禁止。

最后方法的 add 是合法的,因为 <? super E> 形式与 <? extends E> 正好相反,超类型通配符表示 E 的某个父类型,有了它我们就可以更灵活的写入了。

本题特别重要:一定要注意泛型类型声明变量 ?时写数据的规则。

备注:这个主要理解点在这里,就是要让list内部知道是什么数据类型,以至于避免混乱,处于安全性考虑。。。。因为当是<? extends Number>时候,内部按照Number类型处理,Integer和Float就是可以存放的,就不会有问题。。。但是当是<? extends Number>时候,编译器不知道该用什么类型处理,为了避免数据类型出错,

直接就不让add操作了,就出现上面解说的问题了。

问:请说说下面代码片段中注释行执行结果和原因?

  1. Vector<? extends Number> x1 = new Vector<Integer>();    //正确

  2. Vector<? extends Number> x2 = new Vector<String>();    //编译错误

  3. Vector<? super Integer> y1 = new Vector<Number>();    //正确

  4. Vector<? super Integer> y2 = new Vector<Byte>();    //编译错误

答:上面代码编译运行情况如注释所示,本题主要考察泛型中的 ? 通配符的上下边界扩展问题。

通配符对于上边界有如下限制:Vector<? extends 类型1> x = new Vector<类型2>(); 中的类型1指定一个数据类型,则类型2就只能是类型1或者是类型1的子类。

通配符对于下边界有如下限制:Vector<? super 类型1> x = new Vector<类型2>(); 中的类型1指定一个数据类型,则类型2就只能是类型1或者是类型1的父类。

问:下面程序合法吗?

  1. class Bean<T super Student> { //TODO }

答:编译时报错,因为 Java 类型参数限定只有 extends 形式,没有 super 形式。

问:下面程序有什么问题?该如何修复?

  1. public class Test {  

  2.    public static void main(String[] args) throws Exception{  

  3.        List<Integer> listInteger = new ArrayList<Integer>();  

  4.        printCollection(listInteger);    

  5.    }  

  6.    public static void printCollection(Collection<Object> collection) {  

  7.        for(Object obj:collection){  

  8.            System.out.println(obj);  

  9.        }    

  10.    }  

  11. }

答:语句 printCollection(listInteger); 编译报错,因为泛型的参数是没有继承关系的。修复方式就是使用 ?通配符,printCollection(Collection<?> collection),因为在方法 printCollection(Collection<?> collection) 中不可以出现与参数类型有关的方法,譬如 collection.add(),因为程序调用这个方法的时候传入的参数不知道是什么类型的,但是可以调用与参数类型无关的方法,譬如

collection.size()。

问:请解释下面程序片段的执行情况及原因?

  1. public class Test{

  2.    public static <T> T add(T x, T y){  

  3.        return y;

  4.    }

  5.    public static void main(String[] args) {

  6.        int t0 = Test.add(10, 20.8);

  7.        int t1 = Test.add(10, 20);

  8.        Number t2 = Test.add(100, 22.2);

  9.        Object t3 = Test.add(121, "abc");

  10.        int t4 = Test.<Integer>add(10, 20);

  11.        int t5 = Test.<Integer>add(100, 22.2);

  12.        Number t6 = Test.<Number>add(121, 22.2);

  13.    }

  14. }

答:t0 编译直接报错,add 的两个参数一个是 Integer,一个是 Float,所以取同一父类的最小级为 Number,故 T 为 Number 类型,而 t0 类型为 int,所以类型错误。

t1 执行赋值成功,add 的两个参数都是 Integer,所以 T 为 Integer 类型。

t2 执行赋值成功,add 的两个参数一个是 Integer,一个是 Float,所以取同一父类的最小级为 Number,故 T 为 Number 类型。

t3 执行赋值成功,add 的两个参数一个是 Integer,一个是 Float,所以取同一父类的最小级为 Object,故 T 为 Object 类型。

t4 执行赋值成功,add 指定了泛型类型为 Integer,所以只能 add 为 Integer 类型或者其子类的参数。

t5 编译直接报错,add 指定了泛型类型为 Integer,所以只能 add 为 Integer 类型或者其子类的参数,不能为 Float。

t6 执行赋值成功,add 指定了泛型类型为 Number,所以只能 add 为 Number 类型或者其子类的参数,Integer 和 Float 均为其子类,所以可以 add 成功。

t0、t1、t2、t3 其实演示了调用泛型方法不指定泛型的几种情况,t4、t5、t6 演示了调用泛型方法指定泛型的情况。 在调用泛型方法的时可以指定泛型,也可以不指定泛型;在不指定泛型时泛型变量的类型为该方法中的几种类型的同一个父类的最小级(直到 Object),在指定泛型时该方法中的几种类型必须是该泛型实例类型或者其子类。切记,java 编译器是通过先检查代码中泛型的类型,然后再进行类型擦除,再进行编译的。

问:下面两个方法有什么区别?为什么?

  1. public static <T> T get1(T t1, T t2) {  

  2.    if(t1.compareTo(t2) >= 0);

  3.    return t1;  

  4. }  

  5. public static <T extends Comparable> T get2(T t1, T t2) {

  6.    if(t1.compareTo(t2) >= 0);  

  7.    return t1;  

  8. }

答:get1 方法直接编译错误,因为编译器在编译前首先进行了泛型检查和泛型擦除才编译,所以等到真正编译时 T 由于没有类型限定自动擦除为 Object 类型,所以只能调用 Object 的方法,而 Object 没有 compareTo 方法。

get2 方法添加了泛型类型限定可以正常使用,因为限定类型为 Comparable 接口,其存在 compareTo 方法,所以 t1、t2 擦除后被强转成功。所以类型限定在泛型类、泛型接口和泛型方法中都可以使用,不过不管该限定是类还是接口都使用 extends 和 & 符号,如果限定类型既有接口也有类则类必须只有一个且放在首位,如果泛型类型变量有多个限定则原始类型就用第一个边界的类型变量来替换。

JAVA泛型常见误区相关推荐

  1. java 通配符 类_关于类:具有多个类的Java泛型通配符

    我想要一个类对象,但是我想要强制它所代表的任何类来扩展类A和实现接口B. 我能做到: Class extends ClassA> 或: Class extends InterfaceB> ...

  2. Java 泛型(Generics) 综述

    一. 引子 一般的类和方法,只能使用具体类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 多态 算是一种泛化机制,但对代码的约束还是太强 ...

  3. 万字文详解Java泛型

    文章目录 简介 泛型的优点 为什么提高了安全性? 泛型为什么很重要 泛型类 泛型接口 泛型方法 基本用法(非泛型类中的泛型方法) 泛型类中的泛型方法 泛型方法与可变参数 静态方法与泛型 细枝末节 泛型 ...

  4. java 泛型 父子,Java泛型-mb601cf8a78cc07的博客-51CTO博客

    Java泛型 泛型类 即把不确定的数据元素类型用一个泛型占位符表示@Data public class Person { private T name; private T address; }Per ...

  5. 泛型java博客园,Java深度历险之Java泛型

    Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在JD ...

  6. Java学习笔记(二一)——Java 泛型

    [前面的话] 最近脸好干,掉皮,需要买点化妆品了. Java泛型好好学习一下. [定义] 一.泛型的定义主要有以下两种: 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个 ...

  7. 聊一聊Java 泛型通配符 T,E,K,V,?

    欢迎关注方志朋的博客,回复"666"获面试宝典 | 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者 ...

  8. 聊一聊Java 泛型中的通配符 T,E,K,V,?

    点击上方"方志朋",选择"设为星标" 回复"1024"获取独家整理的学习资料 作者:glmapper juejin.im/post/5d57 ...

  9. Java 泛型 T,E,K,V,?,傻傻分不清?

    前言 ​ Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的 ...

最新文章

  1. 心得丨对于机器学习,到底该选择哪种编程语言
  2. springboot自定义异常处理
  3. java判断键盘按键按下_JAVA 从键盘输入一个字符串 判断其是否能被转换为一个有效的数字,字符串可以按位取出...
  4. android上传头像 sockettimeoutexception,Kotlin - Retrofit2和Rxjava2封装的网络请求类(含图片上传)...
  5. 关于ABST2的若干问题
  6. 一文直击Graph Embedding图表示学习的原理及应用
  7. Enterprise search result view column显示technical name
  8. Halcon —— 图像像素类型与转换
  9. 设计模式——————观察者模式
  10. 信息学奥赛一本通(1253:抓住那头牛)
  11. 带命名空间的XML的dom4j应用转
  12. 批处理脚本手动双击可以执行,但计划任务中执行失败
  13. 新房装修有哪些除味小妙招?
  14. 七种方式教你在 SpringBoot 初始化时搞点事情
  15. Luogu3205 合唱队
  16. 不同光栅的结构特点、优缺点以及光栅的选择
  17. 奇舞周刊第 444 期:浅谈文档的实时协同编辑
  18. ubuntu上通过命令行导出mysql数据库文件到widows系统上
  19. matlab统计学分析函数
  20. VMware虚拟机三种网络连接模式详解

热门文章

  1. 音乐编曲软件cubase pro 12.06 安装教程 2023
  2. word图片无法居中,原因可能是非嵌入式!
  3. 前端大文件上传解决方案
  4. 初学unity3D小结
  5. 你最拿手的5种程序设计语言是什么?
  6. vue2.0 + router 3. 0 动态添加路由
  7. 修改apk文件生成路径
  8. 网站搜索引擎优化SEO面试题库和答案(SEO 主管、网站管理员、网站优化师、数字营销专家等)
  9. 市场调研、分析的理论与实践【1】
  10. 第2次作业:软件分析之Steam