




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、12.1 Java类加载机制前面我们给大家介绍过JVM的功能(提供运行时环境、垃圾回收机制和提供中立的体系结构)。在提供运行时环境中有个子功能是ClassLoader(类加载器),它主要用于将主类(即包含了main方法的类)加载到JVM的code segment(代码区)。然后运行环境找到main方法(程序入口)开始执行程序。在整个程序运行的过程中,会有更多的class被动态Load到内存中。类加载机制如图12-1所示:图12-1 类加载机制需要注意的是:类并非一次性就全部加载完毕,而是在需要的时候(运行期间)动态加载到内存。利用java -verbose:class Test可以观察类的具体
2、加载过程。12.2 Java反射机制什么是反射Java 程序在运行期间可以动态加载、解析和使用一些在编译阶段并不确定的类型数据,这一机制被称为反射(Reflection)。反射库(reflection library)提供了一个非常丰富且精心设计的工具类,以便编写能够动态操纵Java代码的程序。使用反射,在设计和运行中添加新类时,能够快速的应用开发工具动态的查询新添加类的能力。反射方式反射机制提供的功能加载运行时才能确定的数据类型解析类的结构、分析类的能力、获取其内部信息操作类(进行实例化访问非静态成员,直接利用类名访问静态成员)或其实例(访问属性、调用方法、创建新对象)12.2.1 Clas
3、s类在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识,被称为Class(注意与class的区别)。通过 Class可以完整的得到一个类中的完整结构,包括此类中的方法定义,属性定义等。Class是反射的源头或入口,通过查看JDK帮助手册其常见方法如图:12.2.2 如何获取Class类对象 针对引用数据类型通过ClassLoader的loadClass方法Class c1 = ClassLoader.getSystemClassLoader().loadClass(com.itjob.Person);调用静态方法Class.forName()Cla
4、ss.forName(com.itjob.Person);Class.forName(oracle.jdbc.dirver.OracleDriver);调用Object类中定义的getClass()方法Person p = new Person();Class c1 = p.getClass();Class c2 = Hello.getClass();使用.class表达式Class c1 = String.class;Class c2 = com.itjob.Person.class;Class c3 = oracle.jdbc.dirver.OracleDriver.class;12.2.
5、2.2 针对基本数据类型及void使用.class 表达式Class c1 = int.class;Class c2 = double.class;Class c3 = void.class;调用相应封装类的Type 属性Class c1 = Integer.TYPE;Class c2 = Double.TYPE;Class c3 = Void.TYPE;示例如下:try /1. 引用数据类型/1.1 利用ClassLoader类的loaderClass(类全名称);手动加载,会有异常System.out.println(ClassLoader.getSystemClassLoader().l
6、oadClass(com.itjob.Person ).getName();/1.2 利用Class.forName(类全名称);手动加载,会有异常System.out.println(Class.forName(com.itjob.Person).getName();/1.3 调用Object类中定义的getClass()方法System.out.println(new Person().getClass().getName();/1.4 使用.class表达式System.out.println(Person.class.getName();/2. 基本数据类型和void/2.1 使用.c
7、lass表达式System.out.println(int.class.getName();System.out.println(double.class.getName();System.out.println(void.class.getName();/2.2 通过各自的包装类.TYPESystem.out.println(Integer.TYPE);System.out.println(Double.TYPE); catch (ClassNotFoundException e) e.printStackTrace();12.2.3 获取实例对象不光可以取得对象所在类的信息,也可以直接通过
8、Class类的newInstance方法进行对象实例化操作。newInstance方法原型如下:public T newInstance() throws InstantiationException,IllegalAccessException调用过程:p.getClass().newInstance();或:Person.class.newInstance();或:Class.forName(com.itjob.Person).newInstance()创建一个Person类的实例。newInstance方法调用默认的构造器初始化新创建的对象,如果这个类没有默认的构造器,就会抛出一个异常。
9、要想调用有参构造方法,则必须使用Constructor类的newInstance方法。12.2.4 获取类的结构Class类的实例用于表示运行时的Java数据类型,包括类、接口、数组、枚举、注解、基本数据类型。在类加载时,Java虚拟机会自动创建相应Class对象。通过反射得到一个类的完整结构要使用到java.lang.reflect包,此包下的常见类如下:java.lang.reflect.Fieldjava.lang.reflect.Methodjava.lang.reflect.Constructorjava.lang.reflect.Modifierjava.lang.reflect.
10、Array 获取类实现的所有接口要想取得一个类所实现的全部接口,则必须使用 Class类中的getInterfaces()方法。此方法定义如下:public Class getInterfaces()。因为一个类可以同时实现多个接口,因此此方法返回一个Class类的对象数组,之后就可以直接利用Class类中的getName()方法输出即可。示例如下:interface Ainterface Bclass Person implements A, Bpublic class Test public static void main(String args) Class c = P
11、erson.class.getInterfaces();for(Class cc : c)System.out.println(cc.getName(); 获取类所继承的父类一个类可以实现多个接口,但是只能继承一个父类,如果没有明确的指明继承那个类,则肯定继承的是Object类。所以要想取得一个类的父类,可以直接使用Class类中的getSuperclass()方法。此方法定义如下:public Class getSuperclass()。此方法返回的是Class实例,和之前得到接口一样,可以通过getName()方法取得名称。 示例如下:class Aclass Person
12、 extends Apublic class Test public static void main(String args) System.out.println(Person.class.getSuperclass().getName(); 获取类中的全部构造方法可以直接使用Class类中的getConstructors()方法或getDeclaredConstructors()方法取得本类中的全部构造方法。这两个方法的返回类型都是Constructor的数组。Constructor类定义在java.lang.reflect包中,常用方法如下:取得访问修饰权限的时候却发现
13、返回的是一个int数字而不是 public等类型的修饰符关键字。这是因为在整个Java中对于方法的修饰符是使用一顶的数字表示出来的,如图所示:如果要想把这个数字还原成用户可以看懂的关键字,则必须依靠Modifier类完成,此类定义在java.lang.reflect包中。直接使用Modifier类的以下方法即可将修饰符转变:public static String toString(int mod);示例如下:import java.lang.reflect.*;class Personprivate String name;private int age;public Person() pu
14、blic Person(String name, int age) = name;this.age = age;Overridepublic String toString() / TODO Auto-generated method stubreturn 我叫 + + ,我今年 + this.age;public class Test public static void main(String args) /获取所有的构造方法Constructor cs = Person.class.getDeclaredConstructors();for(Con
15、structor c : cs)/遍历所有的构造方法/输出构造方法的修饰符System.out.println(构造器修饰符: + Modifier.toString(c.getModifiers();/输出构造方法名称System.out.println(构造方法名: + c.getName();/输出构造方法所有参数Class ct = c.getParameterTypes();if(ct.length = 0)System.out.println(这是无参的构造方法);elseint i = 0;for(Class p : ct)System.out.println(参数 + (i+1
16、) + : + p.getName();i+;现在我们已经知道如何获取一个类的所有构造方法规范,此时我们可以利用Constructor类的newInstance调用有参的构造方法来实例化对象,其过程如下:1、通过Class类中的getConstructors()方法或getDeclaredConstructors()取得本类中的全部构造方法。2、分析每个构造方法的参数情况,了解每个构造方法的原型。3、通过Class类中的getDeclaredConstructor(Class. parameterTypes)方法,向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。4、通过调
17、用Constructor的newInstance(Object. initargs)方法实例化对象。示例如下:try Constructor c = Person.class.getDeclaredConstructor(String.class, int.class);System.out.println(c.newInstance(张三, 25); catch (IllegalArgumentException e) e.printStackTrace(); catch (InstantiationException e) e.printStackTrace(); catch (Illeg
18、alAccessException e) e.printStackTrace(); catch (InvocationTargetException e) e.printStackTrace();catch (SecurityException e1) e1.printStackTrace(); catch (NoSuchMethodException e1) e1.printStackTrace(); 获取类中的方法要想取得一个类中的全部方法,可以使用Class类中的getDeclaredMethods()方法,此方法返回一个Method类的对象数组,如果要想进一步取得方法的
19、具体信息,例如:方法的参数,抛出的异常声明等等内容,就必须依靠Method类来完成。输出本类中的全部方法:public Method getDeclaredMethods() throws SecurityException输出全部的方法(包括父类中的):public Method getMethods() throws SecurityException方法操作:取得全部的返回值:public Class getReturnType()取得全部的参数:public Class getParameterType()取得修饰符:public int getModifiers()取得异常信息:pu
20、blic Class getExceptionType()示例如下:/ 获得非继承的所有方法Method methods = Person.class.getDeclaredMethods();for (Method m : methods) System.out.print(Modifier.toString(m.getModifiers() + + m.getReturnType().getName() + + m.getName() + ();Class paras = m.getParameterTypes();for (Class p : paras) System.out.prin
21、t(p.getName() + );System.out.println();通过Class类的getMethod方法或getDeclaredMethod方法,根据一个类中的方法名称及参数类型取得Method对象,并通过invoke()方法调用指定的方法。invoke方法原型如下:public Object invoke(Object obj, Object. args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException如果要调用的方法是类的静态方法,obj指定为null即可,然
22、后后面是参数列表。如果是非静态方法,必须传入一个类的实例化对象,然后后面是参数列表。如果方法是无参方法:m.invoke(obj); /非静态m.invoke(null);/静态如果方法带参数:m.invoke(obj, 10, 20);/静态m.invoke(null, 10, 20);/非静态示例如下:Person类中的方法原型:public void fun1(int a, int b);public static void fun2(int a, String b);调用方式:/ 非静态方法调用方式method = Person.class.getDeclaredMethod(fun1
23、, int.class, int.class);method.invoke(obj, 10, 20);/ 静态方法调用方式smethod = Person.class.getDeclaredMethod(fun2, int.class, String.class);smethod.invoke(null, 10, hello world java); 获取类中的属性在反射操作中也同样可以取得一个类中的全部属性,但是在取得属性的时候有以下两种不同的操作:得到本类、实现的接口和父类中的所有公共属性:public Field getFields() throws SecurityEx
24、ception得到本类中的全部属性(包括私有属性):public Field getDeclaredFields() throws SecurityException以上方法返回的都是Field的数组,每一个Field对象就表示类中的一个属性。属性操作:取得属性修饰符:public int getModifiers()取得属性类型:public Class getType()取得属性名称:public String getName()示例如下:/ 获取类中所有的属性Field field = Person.class.getDeclaredFields();for(Field f : fiel
25、d)/ 属性修饰符System.out.print(Modifier.toString(f.getModifiers() + );/ 属性类型System.out.print(f.getType().getName() + );/ 属性名称System.out.println(f.getName();setter()及getter()方法是一个标准的属性的访问方法,如果一个类的属性被封装,则必须通过setter及getter方法设置和取得属性的值。实际上此方法的操作之所以要这样规定,主要原因是由于反射机制可以给予支持的。通过反射可以调用setter()及getter()方法。如果要操作一个类中
26、的属性,则可以通过Field类来完成。而不必麻烦的通过setter()及getter()得到。取得公共属性:public Field getField(String name) throws NoSuchFieldException, SecurityException取得本类属性(包括私有):public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException取得属性内容:public Object get(Object obj) throws IllegalArgumentExce
27、ption,IllegalAccessException设置属性内容:public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException设置属性可见(在访问私有属性的时候,必须让这个属性可见):public void setAccessible(boolean flag) throws SecurityException示例如下:Field f = Person.class.getDeclaredField(name);/name是本类中的私有属性f.setAcces
28、sible(true);/设置其可见f.set(obj, 李四);/设置属性System.out.println(f.get(obj);/取得属性与方法类似,如果类中的属性是static修饰的,则get和set方法中的obj为null即可。获取类结构信息综合实例:package reflect;import java.lang.reflect.*;import java.util.Scanner;public class ReflectTest public static void printConstructors(Class cl)Constructor constructors = cl
29、.getDeclaredConstructors();for(Constructor c : constructors)String name = c.getName();System.out.print( );String modifiers = Modifier.toString(c.getModifiers();if(modifiers.length() 0)System.out.print(modifiers + );System.out.print(name + ();Class paramTypes = c.getParameterTypes();for(int i = 0; i
30、0)System.out.print(, );System.out.print(paramTypesi.getName();System.out.println(););public static void printMethods(Class cl)Method methods = cl.getDeclaredMethods();for(Method m : methods)String name = m.getName();Class retType = m.getReturnType();System.out.print( );String modifiers = Modifier.to
31、String(m.getModifiers();if(modifiers.length() 0)System.out.print(modifiers + );System.out.print(retType.getName() + + name + ();Class paramTypes = m.getParameterTypes();for(int i = 0; i 0)System.out.print(, );System.out.print(paramTypesi.getName();System.out.println(););public static void printField
32、s(Class cl)Field fields = cl.getDeclaredFields();for(Field f : fields)Class type = f.getType();String name = f.getName();System.out.print( );String modifiers = Modifier.toString(f.getModifiers();if(modifiers.length() 0)System.out.print(modifiers + );System.out.println(type.getName() + + name + ;);pu
33、blic static void main(String args) String name = null;if(args.length 0)name = args0;elseScanner in = new Scanner(System.in);System.out.print(Enter class name(eg:java.util.Date):);name = in.next();try Class cl = Class.forName(name);Class supercl = cl.getSuperclass();String modifiers = Modifier.toStri
34、ng(cl.getModifiers();if(modifiers.length() 0)System.out.print(modifiers + );System.out.print(class + name);if(supercl != null & supercl != Object.class)System.out.print( extends + supercl.getName();System.out.print(nn);printConstructors(cl);System.out.println();printMethods(cl);System.out.println();
35、printFields(cl);System.out.println(); catch (ClassNotFoundException e) / TODO Auto-generated catch blocke.printStackTrace();12.2.5 通过反射操作数组反射机制不光只能用在类中,也可以应用在任意的引用数据类型上。当然,这就包含了数组,数组使用 Array类完成。Class类中存在以下一个方法,用于返回一个数组对象的实例:public Class getComponentType ()接下来可以利用java.lang.reflect包中的Array类的有些方法来操作:开辟
36、新数组:public static Object newInstance(Class componentType, int. dimensions) throws IllegalArgumentException, NegativeArraySizeException得到数组指定下标的内容:public static Object get(Object array, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException修改内容:public static void set(Object array,
37、 int index, Object value) throws IllegalArgumentException, ArrayIndexOutOfBoundsException示例如下:int arr = 1, 3, 5, 7, 9;Class c = arr.getClass().getComponentType();/ 创建新数组对象,长度为10Object newArr = Array.newInstance(c, 10);/ 利用set修改指定下标的值Array.set(newArr, 0, 10);Array.set(newArr, 1, 20);/ 利用get返回指定下标的值Sy
38、stem.out.println(数组下标为1的元素为: + Array.get(newArr, 1);12.2.6 反射与Annotation一个Annotation要想让其变得有意义,则必须结合发射机制取得Annotation中设置的全部内容。在 Class类中存在以下几种与Annotation 操作有关的方法:实际应用ORM(实体关系映射orm 即Object-relational mapping)示例如下:package com.itjob;import java.lang.annotation.*;import java.lang.reflect.Field;/ 数据库中的类型列表e
39、num dbType varchar,number/ 该注解指明字段的名称和对应的数据类型Target(value=ElementType.FIELD)Retention(value=RetentionPolicy.RUNTIME)interface ColumnAnnotation public String columnName();/ 数据库中字段的名称public dbType dbtype();/ 数据库中字段的类型/ 该注解指明数据库中表的名称Target(value=ElementType.TYPE)Retention(value=RetentionPolicy.RUNTIME)
40、interface TableAnnotation public String tableName();/数据库中表的名称TableAnnotation(tableName=student)/ 表名称为studentclass Student / 对应表student中字段名sname,类型varcharColumnAnnotation(columnName=sname, dbtype=dbType.varchar)private String name;/ 对应表student中字段名sage,类型numberColumnAnnotation(columnName=sage, dbtype=
41、dbType.number)private int age;public Student(String name, int age) = name;this.age = age;public String getName() return name;public void setName(String name) = name;public int getAge() return age;public void setAge(int age) this.age = age;class ORMHelp/ 把对象转换为相应的sql语句插入到数据库中public void insert(Object table)StringBuilder sb = new StringBuilder();sb.append(insert into );/ 获得对象的Class实例Class c = table.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年中国摩丝行业市场现状调查及投资盈利预测研究报告
- 中国出入境检验检疫行业发展分析及投资风险预警与发展策略研究报告2025-2028版
- 2025-2030年中国拉挤环氧板行业发展方向预测及未来投资规划研究报告
- 中国全涤大小化纤纱行业市场发展前景及发展趋势与投资战略研究报告2025-2028版
- 中国书橱行业市场发展前景及发展趋势与投资战略研究报告2025-2028版
- 2025-2030年中国广告公司行业发展策略及投资竞争力研究报告
- 2025-2030年中国干红葡萄酒行业市场前景预测及投资风险预警报告
- 2025-2030年中国工程机械铸件行业深度调研及发展战略规划研究报告
- 酒店社区关系管理的重要性试题及答案
- 如何评估供应商的质量能力试题及答案
- 全友家居导购员销售流程及常用销售话术
- 2025年建筑施工安全管理人员安全生产考试题库
- 十万头生态养猪场项目可行性报告
- 2025年安全评价师职业资格考试真题回顾与模拟试题
- 2025年陕西省高考适应性检测(三)语文试题及参考答案
- 氟化工艺作业课件
- 2025年4月12日乌鲁木齐市人才引进面试真题及答案解析
- 大学高数函数试题及答案
- 湖北省武汉市2025届高中毕业生四月调研考试语文试卷及答案(武汉四调)
- 2024年法考真题答案解析
- 2025新版上海市房屋租赁合同样本
评论
0/150
提交评论