有以下的代码:

1 try{2 ArrayList lstA = new ArrayList();3 ArrayList lstB = new ArrayList();4

5 //ArrayList c = (ArrayList)lstA;

6

7 Object d =lstA;8 ArrayList e = (ArrayList)d;9 System.out.println("e.toString=" +e.toString());10

11 List f =lstA;12 System.out.println("f.toString=" +f.toString());13

14 if (lstA.getClass() ==lstB.getClass()) {15 System.out.println("lstA.class == lstB.class");16 }else{17 System.out.println("lstA.class != lstB.class");18 }19

20 String[] g = {"","2"};21 Object[] h =(Object[])g;22 System.out.println("h.toString=" +h.toString());23 } catch(Exception ex) {24 System.out.println("cast error!--" +ex.getMessage());25 }

运行以上代码,估计会输出什么?会产生异常吗?

实际上,这些代码都能正常运行。

先看看被注释掉的第 5 行:

ArrayList c = (ArrayList)lstA;

这行会产生编译错误,所以被注释掉了。可是换一种方式却可以通过编译器的检查,也就是接下来的7-9行:

Object d =lstA;

ArrayList e = (ArrayList)d;

System.out.println("e.toString=" + e.toString());

这几行代码不光是骗过编译器,也能够正常运行。

继续看接下来的 11-12 行:

List f =lstA;

System.out.println("f.toString=" + f.toString());

与前面 7-9 行的有所不同的是,前面是对“类型参数”做了转换,而此处是类型本身变了,即将 ArrayList 转为其超类接口 List ,这能行吗?

运行便知!OK,执行通过!

继续看看接下来的 14-18 行:

if (lstA.getClass() ==lstB.getClass()) {

System.out.println("lstA.class == lstB.class");

}else{

System.out.println("lstA.class != lstB.class");

}

猜猜这里输出的结果是什么?

答案是:

"lstA.class == lstB.class"

为什么呢?难道 lstA 和 listB 是同一个类型,可是他们明明一个是 ArrayList,一个是ArrayList 。

原来这就是泛型的障眼法。

与 C# 的泛型不同,java 的泛型实际上更像是个语法上的东西,在运行时是没有“泛型”的存在的,运行时 lstA 和 lstB 的类型都是 ArrayList (或者说等同 ArrayList)。

我们再看看最后的 20-22 行:

String[] g = {"","2"};

Object[] h=(Object[])g;

System.out.println("h.toString=" + h.toString());

这和前面的 11 行类似,对于数组同样也行得通。当然这跟泛型没什么关系,这种称为“协变”,只是形式上与一些泛型的操作类似,所以放在一起比照。

以上全部代码在我本机运行的输出结果如下:

e.toString=[]

f.toString=[]

lstA.class == lstB.class

h.toString=[Ljava.lang.String;@e09713

再看看另外的一个例子:

1 public static voidmain(String[] args) {2 try{3 testCaster1(SQLException.class);4 } catch(SQLException e) {5 System.out.println(String.format("SQLException=[%s]--%s", e.getClass().getName(), e.getMessage()));6 } catch(Exception e) {7 System.out.println(String.format("Exception=[%s]--%s", e.getClass().getName(), e.getMessage()));8 }9

10 try{11 testCaster2(SQLException.class);12 } catch(SQLException e) {13 System.out.println(String.format("SQLException=[%s]--%s", e.getClass().getName(), e.getMessage()));14 } catch(Exception e) {15 System.out.println(String.format("Exception=[%s]--%s", e.getClass().getName(), e.getMessage()));16 }17 }18

19

20 private static void testCaster1(Class clazz) throwsE{21 try{22 throw new SQLException("测试抛出的SQL错误。");23 } catch(Throwable e) {24 throw(E)e;25 }26 }27 private static void testCaster2(Class clazz) throwsE{28 try{29 throw new IOException("测试抛出的IO错误。");30 } catch(Throwable e) {31 throw(E)e;32 }33 }

两个泛型方法 testCaster1 和 testCaster2 的逻辑是一样,用泛型 E 定义了 throws 抛出的异常类型,同时在内部捕捉 Throwable 并将其转换为声明的泛型参数返回。

等等!!

细心的你是不是发现了什么不对劲的地方?...

是的,第 24 行和 31 行,明显异常类型 E 是泛型,调用者指定的具体类型是不确定的,而这两个方法一个抛出 SQLException,一个抛出 IOException,

那接下来的转换要引发 ClassCastException 了吧?

不过答案是否定的!它们运行得很好。

看 main 方法中的 2-8 行,调用 testCaster1 抛出的 SQLException,最终被 catch(SQLException e) 捕捉到。

再看接下来的 10-16 行,调用 testCaster2 抛出的 IOException,最终被 catch(Exception e) 捕捉到。

在 testCaster2 的内部抛出的 IOException 似乎并没有按照调用者指定的泛型参数 SQLException 做强制转换,因为并没有 ClassCastException 发生。

哈哈,这又是泛型的障眼法!

全部输出结果如下:

SQLException=[java.sql.SQLException]--测试抛出的SQL错误。

Exception=[java.io.IOException]--测试抛出的IO错误。

java泛型 例子_关于 Java 泛型的一些有趣的例子相关推荐

  1. Java的泛型特性_学习Java的重中之重!

    Java的"泛型"特性,你以为自己会了 使用Java的小伙伴,对于Java的一些高级特性一定再熟悉不过了,例如集合.反射.泛型.注解等等,这些可以说我们在平时开发中是经常使用到的, ...

  2. java实现泛型检索_高级Java泛型:检索泛型类型参数

    java实现泛型检索 在JDK5中引入Java泛型之后, Java泛型Swift成为许多Java程序的组成部分. 但是,乍一看似乎很简单的Java泛型,程序员很快就会迷失此功能. 大多数Java程序员 ...

  3. java smack 例子_关于JAVA利用smack连接openfire的jar依赖问题

    一.GitHub上的maven依赖 直接使用maven依赖 二.关于smack-4.3.4的jar包相关依赖 有两种方式 ①.引入maven依赖,比4.2.0版本多了一项 ②.可以在https://w ...

  4. java基础知识点_「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !

    " 本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指 ...

  5. java核心教程_核心Java教程

    java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...

  6. ncs java 成都 面试_成都java工程师面试一般都是哪些问题,基础难不难!

    了解了许多学员参加的Java面试,他们表示,面试官提出的基础性问题还是比较多.从这个突破口切入,Java新手想要成功通过面试,基础知识方面也需要准备,今天达内成都Java培训班小编就来给大家分享一些J ...

  7. java se7 变化_[转] Java se 7新特性研究(二)

    今天主要研究Java se 7中异常处理的新功能.从今天开始正在将jdk7的说法改为java se 7跟oracle官网的一致 一.新增了try-with-resource 异常声明 在JDK7中只要 ...

  8. java初始化数据报_初始化java原因

    虚拟机的类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类 即虚拟机的类加载机制. 在Java中,类型的加载.链接 ...

  9. java高级教程_高级Java教程

    java高级教程 课程大纲 学习Java基础很容易. 但是,真正钻研该语言并研究其更高级的概念和细微差别将使您成为一名出色的Java开发人员. 网络上充斥着"软","便宜 ...

  10. java 代码封装_封装 java代码

    Java工程师必知词汇:封装 |名词定义| 封装(Encapsulation)是将数据和处理数据的程序组合起来,仅对外公开接口,达到信息隐藏的功能.封装的优点是能减少耦合.Java定义对象都是在语法中 ...

最新文章

  1. 【JQuery】可直接编辑的表格
  2. MonitorService-监控服务类2
  3. 鸿蒙开发-实现页面跳转与页面返回
  4. Gateway配合sentinel自定义限流_你知道如何使用阿里Sentinel实现接口限流吗?
  5. pfSense Book下载
  6. linqtoxml读写xml
  7. 华为云专家向宇:工欲善其事必先利其器,才能做数据的“管家”
  8. [JS]关于表单的自动运算(已解决)
  9. mapreduce task与spark task对比
  10. 太火了!MyBatis-Plus为啥这么牛?
  11. mod_shout 模块
  12. 爬虫爬取数据时如何快速换IP?极光IP轻松搞定
  13. U盘等无法弹出的解决办法
  14. 如何录制游戏视频中的音频
  15. 各种计算机绘图的应用场合,cad制图员面试技巧
  16. 基本过滤工具之配置前缀列表
  17. python编写12306窗体抢票软件(二)
  18. 如何在Dynamic CRM 2011中使用自定义Workflow
  19. java中数组下标越界的异常_java新手求助 数组下标越界异常
  20. vsto 隐藏前面的列滚动条在后面需要滚动到最前面

热门文章

  1. FlashMapManager
  2. 文件操作-读取文件内容
  3. 服务容错和Hystrix
  4. Spring Session快速入门
  5. mybatis 批量将list数据插入到数据库
  6. c++读取utf8文件_经常在日常工作中处理统一码文件(or其他编码)?这篇必读
  7. Cortex-M3-建立向量表
  8. UCloud想吃科创板的“第一个螃蟹”
  9. git clone的源码在vim打开时是乱码
  10. (三十)java多线程一