文档章节

Java技术----Java泛型详解

hero丶
 hero丶
发布于 2017/04/09 14:18
字数 1848
阅读 3
收藏 0
点赞 0
评论 0

Java技术----Java泛型详解 1.为什么需要泛型 泛型在Java中有很重要的地位,网上很多文章罗列各种理论,不便于理解,本篇将立足于代码介绍、总结了关于泛型的知识。希望能给你带来一些帮助。 先看下面的代码:   List list = new ArrayList();   list.add("CSDN_SEU_Cavin");   list.add(100);   for (int i = 0; i < list.size(); i++) {     String name = (String) list.get(i); //取出Integer时,运行时出现异常   System.out.println("name:" + name);   }     本例向list类型集合中加入了一个字符串类型的值和一个Integer类型的值。(这样合法,因为此时list默认的类型为Object类型)。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他原因,运行时会出现java.lang.ClassCastException异常。为了解决这个问题,泛型应运而生。     2.泛型的使用 Java泛型编程是JDK1.5版本后引入的。泛型让编程人员能够使用类型抽象,通常用于集合里面。 只要在上例中将第1行代码改成如下形式,那么就会在编译list.add(100)时报错。 List<String> list = new ArrayList<String>();   通过List<String>,直接限定了list集合中只能含有String类型的元素,从而在上例中的第6行中,无须进行强制类型转换,因为集合能够记住其中元素的类型信息,编译器已经能够确认它是String类型了。   3.泛型只在编译阶段有效 看下面的代码:   AyyayList<String> a = new ArrayList<String>();   ArrayList b = new ArrayList();   Class c1 = a.getClass();   Class c2 = b.getClass();   System.out.println(a == b); //true     上面程序的输出结果为true。所有反射的操作都是在运行时的,既然为true,就证明了编译之后,程序会采取去泛型化的措施,也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。   上述结论可通过下面反射的例子来印证:   ArrayList<String> a = new ArrayList<String>();   a.add("CSDN_SEU_Cavin");   Class c = a.getClass();   try{       Method method = c.getMethod("add",Object.class);       method.invoke(a,100);       System.out.println(a);   }catch(Exception e){       e.printStackTrace();   }     因为绕过了编译阶段也就绕过了泛型,输出结果为: [CSDN_SEU_Cavin, 100]       4.泛型类和泛型方法 如下,我们看一个泛型类和方法的使用例子,和未使用泛型的使用方法进行了对比,两者输出结果相同,在这里贴出来方便读者体会两者的差异。泛型接口的例子有兴趣可以去找一些资料,这里就不赘述了。 (1)使用泛型的情况 public static class FX<T> {       private T ob; // 定义泛型成员变量          public FX(T ob) {           this.ob = ob;       }          public T getOb() {           return ob;       }          public void showTyep() {           System.out.println("T的实际类型是: " + ob.getClass().getName());       }   }       public static void main(String[] args) {           FX<Integer> intOb = new FX<Integer>(100);           intOb.showTyep();           System.out.println("value= " + intOb.getOb());           System.out.println("----------------------------------");              FX<String> strOb = new FX<String>("CSDN_SEU_Calvin");           strOb.showTyep();           System.out.println("value= " + strOb.getOb());   }   (2)不使用泛型的情况   public static class FX {       private Object ob; // 定义泛型成员变量          public FX(Object ob) {           this.ob = ob;       }          public Object getOb() {           return ob;       }          public void showTyep() {           System.out.println("T的实际类型是: " + ob.getClass().getName());       }   }          public static void main(String[] args) {           FX intOb = new FX(new Integer(100));           intOb.showTyep();           System.out.println("value= " + intOb.getOb());           System.out.println("----------------------------------");              FX strOb = new FX("CSDN_SEU_Calvin");           strOb.showTyep();           System.out.println("value= " + strOb.getOb());       }     输出结果均为: T的实际类型是: java.lang.Integer   value= 100   ----------------------------------   T的实际类型是: java.lang.String   value= CSDN_SEU_Calvin     5.通配符 为了引出通配符的概念,先看如下代码:   List<Integer> ex_int= new ArrayList<Integer>();     List<Number> ex_num = ex_int; //非法的     上述第2行会出现编译错误,因为Integer虽然是Number的子类,但List<Integer>不是List<Number>的子类型。 假定第2行代码没有问题,那么我们可以使用语句ex_num.add(newDouble())在一个List中装入了各种不同类型的子类,这显然是不可以的,因为我们在取出List中的对象时,就分不清楚到底该转型为Integer还是Double了。  因此,我们需要一个在逻辑上可以用来同时表示为List<Integer>和List<Number>的父类的一个引用类型,类型通配符应运而生。在本例中表示为List<?>即可。下面这个例子也说明了这一点,注释已经写的很清楚了。   public static void main(String[] args) {       FX<Number> ex_num = new FX<Number>(100);       FX<Integer> ex_int = new FX<Integer>(200);       getData(ex_num);       getData(ex_int);//编译错误   }      public static void getData(FX<Number> temp) { //此行若把Number换为“?”编译通过       //do something...   }          public static class FX<T> {       private T ob;        public FX(T ob) {           this.ob = ob;       }   }         6.上下边界 看了下面这个上边界的例子就明白了,下界FX<? supers Number>的形式就不做过多赘述了。 public static void main(String[] args) {       FX<Number> ex_num = new FX<Number>(100);       FX<Integer> ex_int = new FX<Integer>(200);       getUpperNumberData(ex_num);       getUpperNumberData(ex_int);   }      public static void getUpperNumberData(FX<? extends Number> temp){         System.out.println("class type :" + temp.getClass());   }          public static class FX<T> {       private T ob;        public FX(T ob) {       this.ob = ob;       }   }       7.泛型的好处 (1)类型安全。  通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。  (2)消除强制类型转换。  消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。 (3)提高性能。  Lits list1 = new ArrayList();   list1.add("CSDN_SEU_Cavin ");   String str1 = (String)list1.get(0);   List<String> list2 = new ArrayList<String>();   list2.add("CSDN_SEU_Cavin ");   String str2 = list2.get(0);   对于上面的两段程序,由于泛型所有工作都在编译器中完成,javac编译出来的字节码是一样的(只是更能确保类型安全),那么何谈性能提升呢?是因为在泛型的实现中,编译器将强制类型转换插入生成的字节码中,但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来了可能。   8.泛型使用的注意事项   (1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。 (2)泛型的类型参数可以有多个。 (3)不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。   if(ex_num instanceof FX<Number>){    }     (4)不能创建一个确切的泛型类型的数组。下面使用Sun的一篇文档的一个例子来说明这个问题:   List<String>[] lsa = new List<String>[10]; // Not really allowed.     Object o = lsa;     Object[] oa = (Object[]) o;     List<Integer> li = new ArrayList<Integer>();     li.add(new Integer(3));     oa[1] = li; // Unsound, but passes run time store check     String s = lsa[1].get(0); // Run-time error: ClassCastException.     这种情况下,由于JVM泛型的擦除机制,在运行时JVM是不知道泛型信息的,所以可以给oa[1]赋上一个ArrayList<Integer>而不会出现异常,但是在取出数据的时候却要做一次类型转换,所以就会出现ClassCastException,如果可以进行泛型数组的声明,上面说的这种情况在编译期将不会出现任何的警告和错误,只有在运行时才会出错。 下面采用通配符的方式是被允许的:   List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.     Object o = lsa;     Object[] oa = (Object[]) o;     List<Integer> li = new ArrayList<Integer>();     li.add(new Integer(3));     oa[1] = li; // Correct.     Integer i = (Integer) lsa[1].get(0); // OK  

本文转载自:blog.csdn.net/seu_calvin/article/details/52230032

共有 人打赏支持
hero丶
粉丝 0
博文 9
码字总数 898
作品 0
哈尔滨
程序员
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
06/21
0
0
Cannot make a static reference to the non-stati...

今天碰到这样一些错误,Eclipse提示Cannot make a static reference to the non-static type T。代码如下: public class DAOFactory<D extends TemplateDAO<B>, B> {private static Map<Str......

开源中国驻成都办事处
2013/05/30
0
0
【转】Java语法糖的味道:泛型与类型擦除

泛型是JDK 1.5的一项新特性,它的本质是参数化类型(Parameterized Type)的应用,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类...

mj4738
2011/11/29
0
0
Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh
06/11
0
0
Java基础之反射(非常重要)

反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)) 一、反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道...

Java-老刘
05/15
0
0
大型互联网架构必备技术——性能调优专题

性能调优 深入内核,直击故障 ,拒绝蒙圈 性能优化如何理解 1、性能基准 2、什么是性能优化 3、衡量标准 JVM调优 1、Jvm虚拟机内存剖析 2、垃圾收集器 3、实战调优案例与解决方案 4、Jvm运行...

Java高级架构
04/15
0
0
Java编程学习之泛型方法的了解 java开发

Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类指定一组相关的类型。 Java泛型是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序...

老男孩Linux培训
05/29
0
0
14、Java并发性和多线程-Java ThreadLocal

以下内容转自http://ifeve.com/java-theadlocal/: Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作。因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有...

easonjim
2017/06/16
0
0
从java程序员到CTO的成长路线图

很多新人不知道从事java开发,具体的发展路径是怎么样的,甚至很多人都不能区分程序猿和攻城师的区别。包括不少小白,从事java开发都半年,甚至1年了,对职业发展还没有清晰的认证。这非常不...

6pker
2013/10/24
0
2
Scala学习笔记(1):Scala语言的来源

Scala是“scalable language”,也就是“可扩展”语言是意思。Scala是一种静态类型语言,它融合了函数式编程和面向对象编程和的思想,前者让它可以很方便快速地构建可用程序,后者则让其具有...

chengyao2
2013/04/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
5
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
1
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
165
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0
开发技术瓶颈期,如何突破

前言 读书、学习的那些事情,以前我也陆续叨叨了不少,但总觉得 “学习方法” 就是一个永远在路上的话题。个人的能力、经验积累与习惯方法不尽相同,而且一篇文章甚至一本书都很难将学习方法...

_小迷糊
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部