版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、12021/3/9JAVA泛型和反射泛型和反射22021/3/9v泛型泛型是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。 32021/3/9v例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象。v因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:42021/3/9vMap m =
2、 new HashMap();m.put(key, blarg);String s = (String) m.get(key); v要让程序通过编译,必须将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。52021/3/9v理想情况下,您可能会得出这样一个观点,即 m 是一个 Map,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型
3、的键或值保存在集合中。这就是泛型泛型所做的工作。62021/3/9泛型的好处泛型的好处 vJava 语言中引入泛型泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型泛型化的了。这带来了很多好处: 72021/3/9v类型安全。 泛型泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。v消除强制类型转换。 泛型泛型的一个附带好
4、处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。 v潜在的性能收益。 泛型泛型为较大的优化带来可能。更多类型信息可用于编译器这一事实,为JVM 的优化带来可能。 82021/3/9使用泛型与不使用泛型的比较。使用泛型与不使用泛型的比较。 v /不使用泛型ArrayListal1=newArrayList();/1al1.add(newInteger(10);/2这里可加入任何对象。Integeri1=(Integer)al1.get(0);/3这里必须做强制类型转换。如果前面程序不小心往al1中放入了非Integer对象,那么程序运行到此将会报一个类型转换异常(j
5、ava.lang.ClassCastException)。/使用泛型ArrayListal2=newArrayList();al2.add(newInteger(10);/这里只能加入Integer对象。Integeri2=al2.get(0);/这里不必做强制类型转换。不用再担心程序会报一个类型转换异常(java.lang.ClassCastException)。92021/3/9泛型基础泛型基础 v在定义泛型泛型类或声明泛型泛型类的变量时,使用尖括号来指定形式类型参数。形式类型参数与实际类型参数之间的关系类似于形式方法参数与实际方法参数之间的关系,只是类型参数表示类型,而不是表示值。v当声
6、明或者实例化一个泛型泛型的对象时,必须指定类型参数的值:vMap map = new HashMap(); 102021/3/9自定义简单泛型自定义简单泛型 publicclassGclassprivateTa;publicTgetA()returna;publicvoidsetA(Ta)this.a=a;112021/3/9泛型泛型 与继承与继承v泛型中有继承的概念吗 v/使用泛型 ArrayList al2=new ArrayList();/1 al2.add(new Integer(10);/2 Integer i2=al2.get(0);/3 ArrayList alO=al2;/这样
7、可以吗?122021/3/9v如果说ArrayList 是一个 ArrayList就可以这么转换的话将出大问题:alO.add(newObject();将是合法的i2=al2.get(1);/这样就会导致类型转换异常。v所以说: ArrayList 不是一个 ArrayList.v这带来另一个后果是,不能实例化泛型类型的数组(new List3 是不合法的)132021/3/9v如果允许声明泛型类型数组 Listlsa=newList10;Objectoa=lsa;Listli=newArrayList();li.add(newInteger(3);oa0=li;Strings=lsa0.ge
8、t(0);v最后一行将抛出 ClassCastException,因为这样将把 List 填入本应是 List 的位置。因为数组继承会破坏泛型的类型安全,所以不允许实例化泛型类型的数组(除非类型参数是未绑定的通配符,比如 List)。 142021/3/9类型通配符类型通配符 public void showCollection2(Collection c) System.out.println(c);v上面代码中的问号是一个类型通配符。List 是任何泛型泛型 List 的父类型,所以完全可以将 List、List或其他传递给 printList()。 152021/3/9类型通配符的作用类
9、型通配符的作用 v下面的代码工作得很好:vList li = new ArrayList();li.add(new Integer(42);List lu = li;System.out.println(lu.get(0);v另一方面,下面的代码不能工作:vList li = new ArrayList();li.add(new Integer(42);List lu = li;lu.add(new Integer(43); / error162021/3/9v对于 lu,编译器不能对 List 的类型参数作出足够严密的推理,以确定将 Integer 传递给 List.add() 是类型安全的
10、。所以编译器将不允许您这么做。下面的代码将能工作,因为它不依赖于编译器必须知道关于 lu 的类型参数的任何信息: vList li = new ArrayList();li.add(new Integer(42);List lu = li;lu.clear(); 172021/3/9有所限制的类型抽象通配符有所限制的类型抽象通配符vpublic class Matrix . v编译器允许创建 Matrix 或 Matrix 类型的变量,但是如果试图定义 Matrix 类型的变量,则会出现错误。类型参数 V 被判断为由 Number 限制 。在没有类型限制时,假设类型参数由 Object 限制。
11、这就是为什么前一屏 泛型泛型方法 中的例子,允许 List.get() 在 List 上调用时返回 Object,即使编译器不知道类型参数 V 的类型。 182021/3/9有所限制的类型抽象通配符有所限制的类型抽象通配符vpublic void showCollection3(Collection c)v v for(Number n:c)v v System.out.println(Value();v v 192021/3/9泛型方法泛型方法 v通过在类的定义中添加一个形式类型参数列表,可以将类泛型泛型化。方法也可以被泛型泛型化,不管它们定义在其中的类是不是泛型泛型化的。 vpu
12、blic T ifThenElse(boolean b, T first, T second)v return b ? first : second; 202021/3/9vifThenElse() 不显式地告诉编译器,想要 T 的什么值。编译器不必显式地被告知 T 将具有什么值;它只知道这些值都必须相同。 vInteger i = ifThenElse(b, new Integer(1), new Integer(2); 是合法的v而String s = ifThenElse(b, “pi”, new Float(3.14); 是非法的,因为有类型不满足所需的类型约束: 212021/3/9
13、方法中泛型的调用方法中泛型的调用/错误的写法publicvoidaddToCollection3(Numbera,Collectionc)for(Numbern:a)c.add(n);/编译错误!/正确的写法publicvoidaddToCollection3(Ta,Collectionc)for(Tn:a)c.add(n);222021/3/9JAVA反射反射v反射反射是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说自审,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。 232021/3/9Java 语言的反射机制
14、语言的反射机制v在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java 语言的反射(Reflection)机制。vJava 反射机制主要提供了以下功能242021/3/9Java 语言的反射机制语言的反射机制v在运行时判断任意一个对象所属的类。v在运行时构造任意一个类的对象。v在运行时判断任意一个类所具有的成员变量和方法。v在运行时调用任意一个对象的方法252021/3/9Java Reflection API 简介简介v在JDK中,主要由以下类来实现Jav
15、a反射机制,这些类都位于java.lang.reflect包中 Class类:代表一个类。 Field类:代表类的成员变量(成员变量也称为类的属性)。 Method类:代表类的方法。 Constructor类:代表类的构造方法。 Array类:提供了动态创建数组,以及访问数组的元素的静态方法262021/3/9v 考虑下面这个简单的例子,让我们看看 反射是如何工作的。 import java.lang.reflect.*;public class DumpMethods public static void main(String args) try Class c = Class.forNa
16、me(args0);Method m = c.getDeclaredMethods();for (int i = 0; i m.length; i+)System.out.println(mi.toString(); catch (Throwable e) System.err.println(e); 272021/3/9v按如下语句执行:java DumpMethods java.util.Stackv这样就列出了java.util.Stack 类的各方法名以及它们的限制符和返回类型。v这个程序使用 Class.forName 载入指定的类,然后调用 getDeclaredMethods 来
17、获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。 282021/3/9v使用反射的时候必须要遵循三个步骤:v第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中,用 java.lang.Class 类来描述类和接口等。 v下面就是获得一个 Class 对象的方法之一:Class c = Class.forName(java.lang.String);还有另一种方法,如下面的语句:Class c = int.class;292021/3/9v在java.lang.Object 类中定义
18、了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法 getName():获得类的完整名字。 getFields():获得类的public类型的属性。 getDeclaredFields():获得类的所有属性。 getMethods():获得类的public类型的方法。 getDeclaredMethods():获得类的所有方法。302021/3/9vgetMethod(String name, Class parameterTypes):获得类的特定方法,name参数指定方法的名字,pa
19、rameterTypes 参数指定方法的参数类型。vgetConstructors():获得类的public类型的构造方法。vgetConstructor(Class parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。vnewInstance():通过类的不带参数的构造方法创建这个类的一个对象。312021/3/9v第二步是调用诸如 getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。v一旦取得这个信息,就可以进行第三步了使用 reflection API 来操作这些信息,如下面这段代码:Class c
20、= Class.forName(java.lang.String);Method m = c.getDeclaredMethods();System.out.println(m0.toString();v它将以文本方式打印出 String 中定义的第一个方法的原型。 322021/3/9v得到类信息之后,通常下一个步骤就是解决关于 Class 对象的一些基本的问题。例如,Class.isInstance 方法可以用于模拟 instanceof 操作符: 332021/3/9v public class instance1 public static void main(String args)
21、 try Class cls = Class.forName(A);boolean b1 = cls.isInstance(new Integer(37);System.out.println(b1);boolean b2 = cls.isInstance(new A();System.out.println(b2); catch (Throwable e) System.err.println(e); v 在这个例子中创建了一个 A 类的 Class 对象,然后检查一些对象是否是 A 的实例。342021/3/9v找出一个类中定义了些什么方法,这是一个非常有价值也非常基础的 reflecti
22、on 用法。下面的代码就实现了这一用法: 352021/3/9 Class cls = Class.forName(“className);Method methlist = cls.getDeclaredMethods();for (int i = 0; i methlist.length; i+) Method m = methlisti;System.out.println(name = + m.getName();System.out.println(decl class = + m.getDeclaringClass();Class pvec = m.getParameterType
23、s();for (int j = 0; j pvec.length; j+)System.out.println(param # + j + + pvecj);Class evec = m.getExceptionTypes();for (int j = 0; j evec.length; j+)System.out.println(exc # + j + + evecj);System.out.println(return type = + m.getReturnType();System.out.println(-);362021/3/9v这个程序首先取得 className类的描述,然后
24、调用 getDeclaredMethods 来获取一系列的 Method 对象,它们分别描述了定义在类中的每一个方法,包括 public 方法、protected 方法、package 方法和 private 方法等。如果你在程序中使用 getMethods 来代替 getDeclaredMethods,你还能获得继承来的各个方法的信息。取得了 Method 对象列表之后,要显示这些方法的参数类型、异常类型和返回值类型等就不难了。这些类型是基本类型还是类类型,都可以由描述类的对象按顺序给出。372021/3/9v获取构造器信息获取构造器信息 v获取类构造器的用法与上述获取方法的用法类似,如:
25、382021/3/9 Class cls = Class.forName(className);Constructor ctorlist = cls.getDeclaredConstructors();for (int i = 0; i ctorlist.length; i+) Constructor ct = ctorlisti;System.out.println(name = + ct.getName();System.out.println(decl class = + ct.getDeclaringClass();Class pvec = ct.getParameterTypes()
26、;for (int j = 0; j pvec.length; j+)System.out.println(param # + j + + pvecj);Class evec = ct.getExceptionTypes();for (int j = 0; j evec.length; j+)System.out.println(exc # + j + + evecj);System.out.println(-);这个例子中没能获得返回类型的相关信息,那是因为构造器没有返回类型。 392021/3/9v获取类的字段获取类的字段(域域) v找出一个类中定义了哪些数据字段也是可能的,下面的代码就在
27、干这个事情: 402021/3/9v Class cls = Class.forName(field1);Field fieldlist = cls.getDeclaredFields();for (int i = 0; i fieldlist.length; i+) Field fld = fieldlisti;System.out.println(name = + fld.getName();System.out.println(decl class = + fld.getDeclaringClass();System.out.println(type = + fld.getType();
28、int mod = fld.getModifiers();System.out.println(modifiers = + Modifier.toString(mod);System.out.println(-);412021/3/9v这个例子和前面那个例子非常相似。例中使用了一个Modifier,它也是一个 reflection 类,用来描述字段成员的修饰语,如“private int”。这些修饰语自身由整数描述,而且使用 Modifier.toString 来返回以“官方”顺序排列的字符串描述 (如“static”在“final”之前)。:和获取方法的情况一下,获取字段的时候也可以只取得在
29、当前类中申明了的字段信息 (getDeclaredFields),或者也可以取得父类中定义的字段 (getFields) 。 422021/3/9v根据方法的名称来执行方法根据方法的名称来执行方法 v到这里,所举的例子无一例外都与如何获取类的信息有关。我们也可以用 reflection 来做一些其它的事情,比如执行一个指定了名称的方法。 432021/3/9v Class cls = Class.forName(method2);Class partypes = new Class2;partypes0 = Integer.TYPE;partypes1 = Integer.TYPE;Metho
30、d meth = cls.getMethod(add, partypes);method2 methobj = new method2();Object arglist = new Object2;arglist0 = new Integer(37);arglist1 = new Integer(47);Object retobj = meth.invoke(methobj, arglist);Integer retval = (Integer) retobj;System.out.println(Value(); 442021/3/9v假如一个程序在执行的某处的时候才知道需要执行某个方法,这个方法的名称是在程序的运行过程中指定的,那么上面的程序演示了如何做到。 v上例中, getMethod用于查找一个具有两个整型参数且名为 add 的方法。找到该方法并创建
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 企业培训数据报表管理方案
- 露天矿山设备租赁管理方案
- 老旧小区网络流量管理方案
- 建筑广播与背景音乐系统方案
- 加油站运营区域土建布局优化方案
- 监理工作实施方案
- 固废处置场新建项目施工方案
- 公司项目立项管理方案
- 公司基于大数据的供应链优化方案
- 高风险化学品使用安全管理方案
- 2024秋期国家开放大学专科《企业法务》一平台在线形考(任务1至4)试题及答案
- 1.句型(讲解)-2025年中考英语
- DB34T∕ 2593-2016 水栀子扦插育苗技术规程
- 11BS3给水工程华北标图集
- GB/T 34924-2024低压电气设备安全风险评估和风险降低指南
- 自考离散数学串讲
- 2023电站锅炉安装、改造和重大修理监督检验规程
- 线路架设工详细上岗岗前培训制度培训
- 市政隧道盾构工程施工质量验收表格
- Photoshop教案及课件全套表格版
- T-CSSS 002-2023 健康成年人身体活动能量消耗参考值
评论
0/150
提交评论