Java反射学习笔记
2015-12-27 23:55
477 查看
一 定义及功能
Java的反射机制指的是,Java程序在运行过程中,对于任意一个类,都能够动态的获得这个类的任意的属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取对象属性和方法的功能称为Java语言的反射机制。
Java反射机制可以提供一下功能:
1 在运行时判断任意一个对象所属的类;
2 在运行时调用任意一个对象的方法;
3 在运行时判断任意一个类所具有的的成员变量和方法;
4 在运行时构造任意一个类的对象;
5 生成动态代理;
我们首先使用一个例子来说明Java反射机制是如何工作的。
输出结果:
reflect.test.Demo
这样就可以获得demo对象所属的类的命名空间和类名。这个过程使用了对象的getClass()方法来载入指定的类,然后调用getName()方法来获取名称。
二 获取步骤及方式
使用Java的反射机制,需要遵循三个步骤:
1 获得你要操作的类的Class对象;
2 通过第一步获得的class对象,获取要操作的类的方法名或者属性对象;
3 操作第二步获取的属性或者对象。
Java运行的时候,无论某个类实例化多少个对象,他们都会对应一个Class对象,它表示正在运行的程序的类和接口。如何获取这个类呢?常用的方法有三个:
1 通过Class的静态方法forName(),直接输入类的全路径;
2 通过对象的getClass()方法,获得所指向的Class对象。
3 通过类名的.class语法,获得Class对象;
下面通过实例来说明,如何通过以上三个方法获取Class对象。
输出结果:
java.lang.String
java.lang.String
java.lang.String
三 功能详解
前边我们说过了反射的五个主要用途,我们已经试验了第一个用途,通过反射获得对象所属的类,下面我们分别来说明其他的几个用途。
1 通过反射来执行对象的某个方法,代码如下:
输出结果:
小盖 你好!
前边说过,使用反射的第一步就是获取这个类,对应我们代码注释的第一步;第二步是获取你将要操作的方法对象,对应我们代码第二步,这个方法包括三个参数,第一个参数是我们要操作的那个方法名,第二个和第三个参数分别是我们要调用的那个方法的参数类型,这个方法的参数个数是根据要调用的方法的参数个数来确定的,所以,参数个数是个不确定的数据。第三步是执行这个方法,即我们的invoke方法,其实调用的就是show方法,这个方法有三个参数,第一个参数是一个对象,使我们要调用的那个类的一个对象,后边的参数是我们要调用的方法需要的参数,这个参数必须与要调用方法的参数一致。
2 通过反射来给某个类的属性赋值,代码如下:
运行结果:
小盖 : 22
反射机制中的类有Class对应,方法有Method对应,属性由Field对应。Field提供了get和set属性,但是由于属性时私有类型,所以需要设置访问权限。本例中是通过循环分别为每个属性设置访问权限,您也可以通过设置属性集的权限来同意修改访问权限,在此不再赘述。
3 通过反射在运行时动态创建类的一个对象,代码如下:
输出结果:
姓名: 小盖
学号: 11050241003
Class的newInstance方法只能创建无参数的构造函数的类,如果构造函数带有参数,那么就需要另外一种方式。属性赋值和上例一样,这里不再赘述。
四 注意事项
在获取类的方法、属性和构造函数时,会有getxxx和getDeclatedxxx两种方法。它们的区别是前者只能返回访问权限为public的方法和属性,包括父类的;后者返回的是所有访问权限的方法和属性,不包括父类的。
五 总结
反射的应用范围很广,使用反射可以降低程序之间的耦合性,增加程序的灵活性。
以后会根据实际应用情况更加深入的研究反射,敬请期待。
Java的反射机制指的是,Java程序在运行过程中,对于任意一个类,都能够动态的获得这个类的任意的属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取对象属性和方法的功能称为Java语言的反射机制。
Java反射机制可以提供一下功能:
1 在运行时判断任意一个对象所属的类;
2 在运行时调用任意一个对象的方法;
3 在运行时判断任意一个类所具有的的成员变量和方法;
4 在运行时构造任意一个类的对象;
5 生成动态代理;
我们首先使用一个例子来说明Java反射机制是如何工作的。
<span style="font-size:18px;">package reflect.test;</span>
<span style="font-size:18px;"> import java.lang.reflect.Method; //测试类 class Demo { } public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { <span style="white-space:pre"> </span>Demo demo = new Demo(); System.out.println(demo.getClass().getName()); } }</span>
输出结果:
reflect.test.Demo
这样就可以获得demo对象所属的类的命名空间和类名。这个过程使用了对象的getClass()方法来载入指定的类,然后调用getName()方法来获取名称。
二 获取步骤及方式
使用Java的反射机制,需要遵循三个步骤:
1 获得你要操作的类的Class对象;
2 通过第一步获得的class对象,获取要操作的类的方法名或者属性对象;
3 操作第二步获取的属性或者对象。
Java运行的时候,无论某个类实例化多少个对象,他们都会对应一个Class对象,它表示正在运行的程序的类和接口。如何获取这个类呢?常用的方法有三个:
1 通过Class的静态方法forName(),直接输入类的全路径;
2 通过对象的getClass()方法,获得所指向的Class对象。
3 通过类名的.class语法,获得Class对象;
下面通过实例来说明,如何通过以上三个方法获取Class对象。
<span style="font-size:18px;">package reflect.test; import java.lang.reflect.Method; //测试类 class Demo { } public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { // 三种方式获取操作类的class对象 Class<?> demo1 = null; Class<?> demo2 = null; Class<?> demo3 = null; // 方法一 通过输入String类的全路径 try { demo1 = Class.forName("java.lang.String"); } catch (Exception e) { e.printStackTrace(); } // 方法二 通过实例化后的对象得到Class类 String strTest = ""; demo2 = strTest.getClass(); // 方法三 通过类的class语法,获取Class类 demo3 = String.class; // 输出Class类 System.out.println(demo1.getName()); System.out.println(demo2.getName()); System.out.println(demo3.getName()); } }</span>
输出结果:
java.lang.String
java.lang.String
java.lang.String
三 功能详解
前边我们说过了反射的五个主要用途,我们已经试验了第一个用途,通过反射获得对象所属的类,下面我们分别来说明其他的几个用途。
1 通过反射来执行对象的某个方法,代码如下:
<span style="font-size:18px;">package reflect.test; import java.lang.reflect.Method; //测试类 class Display { // 带有参数的输出方法 public void show(String name, String content) { System.out.println(name + content); } } public class ReflectMethod { public static void main(String[] args) { // 1 获取display类的对象 Display display = new Display(); Class<?> displayTest = display.getClass(); // 2 获取操作方法对象 Method method = null; try { method = displayTest.getMethod("show", String.class, String.class); } catch (Exception e) { e.printStackTrace(); } //3 执行获得的方法 try { method.invoke(display, "小盖", "你好!"); } catch (Exception e) { e.printStackTrace(); } } }</span>
输出结果:
小盖 你好!
前边说过,使用反射的第一步就是获取这个类,对应我们代码注释的第一步;第二步是获取你将要操作的方法对象,对应我们代码第二步,这个方法包括三个参数,第一个参数是我们要操作的那个方法名,第二个和第三个参数分别是我们要调用的那个方法的参数类型,这个方法的参数个数是根据要调用的方法的参数个数来确定的,所以,参数个数是个不确定的数据。第三步是执行这个方法,即我们的invoke方法,其实调用的就是show方法,这个方法有三个参数,第一个参数是一个对象,使我们要调用的那个类的一个对象,后边的参数是我们要调用的方法需要的参数,这个参数必须与要调用方法的参数一致。
2 通过反射来给某个类的属性赋值,代码如下:
<span style="font-size:18px;">package reflect.test; import java.lang.reflect.Field; //测试实体类 class Person{ private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } public class ReflectAttribute { public static void main(String[] args){ //实例化一个源对象并且赋值 Person fromPerson = new Person(); fromPerson.setName("小盖"); fromPerson.setAge(22); //实例化一个目标对象 Person toPerson = new Person(); try { //给目标对象属性赋值 replace(fromPerson, toPerson); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } System.out.println(toPerson.getName() +" : "+ toPerson.getAge().toString()); } public static void replace (Object fromClass,Object toClass) throws SecurityException, NoSuchFieldException{ //获取源对象的类 Class<?> fromObject = fromClass.getClass(); //获取源对象的属性集 Field[] fromFields = fromObject.getDeclaredFields(); //获取目标对象的类 Class<?> toObject = toClass.getClass(); //定义目标对象的属性集 Field toField = null; //循环源对象属性集 for (Field fromField : fromFields) { //获取源对象的属性名称和对应目标对象的属性名称 String name = fromField.getName(); toField = toObject.getDeclaredField(name); //设置属性操作权限 fromField.setAccessible(true); toField.setAccessible(true); try { //给目标对象属性赋值 toField.set(toClass, fromField.get(fromClass)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } }</span>
运行结果:
小盖 : 22
反射机制中的类有Class对应,方法有Method对应,属性由Field对应。Field提供了get和set属性,但是由于属性时私有类型,所以需要设置访问权限。本例中是通过循环分别为每个属性设置访问权限,您也可以通过设置属性集的权限来同意修改访问权限,在此不再赘述。
3 通过反射在运行时动态创建类的一个对象,代码如下:
<span style="font-size:18px;">package reflect.test; import java.lang.reflect.Field; class Student{ private String stuName; private String stuNo; public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public String getStuNo() { return stuNo; } public void setStuNo(String stuNo) { this.stuNo = stuNo; } } public class ReflectClass { public static void main (String[] args){ //实例化源对象 Student fromStudent = new Student(); fromStudent.setStuName("小盖"); fromStudent.setStuNo("11050241003"); //调用replace方法生成目标对象 Student toStudent = (Student)replace(fromStudent); System.out.println("姓名: " + toStudent.getStuName()); System.out.println("学号: " + toStudent.getStuNo()); } private static Object replace(Object fromClass){ //1--2 获得源对象的类和属性集、定义目标对象 Class<?> fromObject = fromClass.getClass(); Field[] fromFields = fromObject.getDeclaredFields(); Object toObject = null; try { //3 通过类直接创建目标对象 toObject = fromObject.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } //给目标对象创建属性等 for (Field fromField : fromFields) { fromField.setAccessible(true); try { fromField.set(toObject, fromField.get(fromClass)); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return toObject; } }</span>
输出结果:
姓名: 小盖
学号: 11050241003
Class的newInstance方法只能创建无参数的构造函数的类,如果构造函数带有参数,那么就需要另外一种方式。属性赋值和上例一样,这里不再赘述。
四 注意事项
在获取类的方法、属性和构造函数时,会有getxxx和getDeclatedxxx两种方法。它们的区别是前者只能返回访问权限为public的方法和属性,包括父类的;后者返回的是所有访问权限的方法和属性,不包括父类的。
五 总结
反射的应用范围很广,使用反射可以降低程序之间的耦合性,增加程序的灵活性。
以后会根据实际应用情况更加深入的研究反射,敬请期待。
相关文章推荐
- 正则表达式及其范例
- Java实现人民币大写精讲
- Java内存管理和垃圾回收
- java 遍历map
- java 遍历map
- java判断字符串为空的方法
- java判断字符串为空的方法
- java volatile详解
- 使用springmvc后事物不起作用的原因
- spring有三种启动方式
- java servlet+mysql全过程(原创)
- Java toString() method
- 【跟我学spring 4.0 】之第六节-spring中scope作用域
- [一]java环境变量的配置
- Java之泛型
- Java 匿名类
- Java 通过JDBC连接Mysql数据库的方法和实例
- JavaScrip——DOM操作(查找HTML元素/修改元素)
- [六]JFreeChart实践五之与Struts2整合
- java的reflection和introspector