`
hongwei3344661
  • 浏览: 31322 次
  • 性别: Icon_minigender_1
文章分类
社区版块
存档分类
最新评论

java反射

 
阅读更多

 Java反射机制是在运行状态中,对于任意一个,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。当然反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。

      Java反射机制主要提供下面几种用途:

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法

      首先看一个简单的例子,通过这个例子来理解Java的反射机制是如何工作的。

复制代码
package com.wanggc.reflection;

import java.lang.reflect.Method;

/**
* Java 反射练习。
*
*
@author Wanggc
*/
public class ForNameTest {

/**
* 入口函数。
*
*
@param args
* 参数
*
@throws Exception
* 错误信息
*/
public static void main(String[] args) throws Exception {
// 获得Class
Class<?> cls = Class.forName(args[0]);
// 通过Class获得所对应对象的方法
Method[] methods = cls.getMethods();
// 输出每个方法名
for (Method method : methods) {
System.out.println(method);
}
}
}
复制代码

      当传入的参数是java.lang.String时,会输出如下结果

View Code

      这样就列出了java.lang.String类的所有方法名、及其限制符、返回类型及抛出的异常。这个程序使用Class类forName方法载入指定的类,然后调用getMethods方法返回指定类的方法列表。java.lang.reflect.Method用来表述某个类中的单一方法。

      使用java的反射机制,一般需要遵循三步:

    1. 获得你想操作类的Class对象
    2. 通过第一步获得的Class对象去取得操作类的方法或是属性名
    3. 操作第二步取得的方法或是属性

     Java运行的时候,某个类无论生成多少个对象,他们都会对应同一个Class对象,它表示正在运行程序中的类和接口。如何取得操作类的Class对象,常用的有三种方式:

    1. 调用Class的静态方法forName,如上例;
    2. 使用类的.class语法,如:Class<?> cls = String.class;
    3. 调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();

      下面将通过实例讲述如何通过前面所诉的三步来执行某对象的某个方法:

复制代码
 1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Method;
4
5 /**
6 * Java 反射练习。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 DisPlay disPlay = new DisPlay();
13 // 获得Class
14 Class<?> cls = disPlay.getClass();
15 // 通过Class获得DisPlay类的show方法
16 Method method = cls.getMethod("show", String.class);
17 // 调用show方法
18 method.invoke(disPlay, "Wanggc");
19 }
20 }
21
22 class DisPlay {
23 public void show(String name) {
24 System.out.println("Hello :" + name);
25 }
26 }
复制代码

      前面说过,Java程序的每个类都会有个Class对象与之对应。Java反射的第一步就是获得这个Class对象,如代码14行。当然,每个类的方法也必有一个Method对象与之对应。要通过反射的方式调用这个方法,就要首先获得这个方法的Method对象,如代码16行,然后用Method对象反过来调用这个方法,如代码18行。注意16行getMethod方法的第一个参数是方法名,第二个是此方法的参数类型,如果是多个参数,接着添加参数就可以了,因为getMethod是可变参数方法。执行18行代码的invoke方法,其实也就是执行show方法,注意invoke的第一个参数,是DisPlay类的一个对象,也就是调用DisPlay类哪个对象的show方法,第二个参数是给show方法传递的参数。类型和个数一定要与16行的getMethod方法一直。

      上例讲述了如何通过反射调用某个类的方法,下面将再通过一个实例讲述如何通过反射给某个类的属性赋值:

复制代码
  1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Field;
4
5 /**
6 * Java 反射之属性练习。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 // 建立学生对象
13 Student student = new Student();
14 // 为学生对象赋值
15 student.setStuName("Wanggc");
16 student.setStuAge(24);
17 // 建立拷贝目标对象
18 Student destStudent = new Student();
19 // 拷贝学生对象
20 copyBean(student, destStudent);
21 // 输出拷贝结果
22 System.out.println(destStudent.getStuName() + ":"
23 + destStudent.getStuAge());
24 }
25
26 /**
27 * 拷贝学生对象信息。
28 *
29 * @param from
30 * 拷贝源对象
31 * @param dest
32 * 拷贝目标对象
33 * @throws Exception
34 * 例外
35 */
36 private static void copyBean(Object from, Object dest) throws Exception {
37 // 取得拷贝源对象的Class对象
38 Class<?> fromClass = from.getClass();
39 // 取得拷贝源对象的属性列表
40 Field[] fromFields = fromClass.getDeclaredFields();
41 // 取得拷贝目标对象的Class对象
42 Class<?> destClass = dest.getClass();
43 Field destField = null;
44 for (Field fromField : fromFields) {
45 // 取得拷贝源对象的属性名字
46 String name = fromField.getName();
47 // 取得拷贝目标对象的相同名称的属性
48 destField = destClass.getDeclaredField(name);
49 // 设置属性的可访问性
50 fromField.setAccessible(true);
51 destField.setAccessible(true);
52 // 将拷贝源对象的属性的值赋给拷贝目标对象相应的属性
53 destField.set(dest, fromField.get(from));
54 }
55 }
56 }
57
58 /**
59 * 学生类。
60 */
61 class Student {
62 /** 姓名 */
63 private String stuName;
64 /** 年龄 */
65 private int stuAge;
66
67 /**
68 * 获取学生姓名。
69 *
70 * @return 学生姓名
71 */
72 public String getStuName() {
73 return stuName;
74 }
75
76 /**
77 * 设置学生姓名
78 *
79 * @param stuName
80 * 学生姓名
81 */
82 public void setStuName(String stuName) {
83 this.stuName = stuName;
84 }
85
86 /**
87 * 获取学生年龄
88 *
89 * @return 学生年龄
90 */
91 public int getStuAge() {
92 return stuAge;
93 }
94
95 /**
96 * 设置学生年龄
97 *
98 * @param stuAge
99 * 学生年龄
100 */
101 public void setStuAge(int stuAge) {
102 this.stuAge = stuAge;
103 }
104 }
复制代码

       Java的发射机制中类有Class对应,类的方法有Method对应,当然属性也有Field与之对应。代码中注释已经做了详细的注释,在此不再赘述。但要注意,Field提供了get和set方法获取和设置属性的值,但是由于属性是私有类型,所以需要设置属性的可访问性为true,如代码50~51行。也可以在为整个fields设置可访问性,在40行下面使用AccessibleObject的静态方法setAccessible,如:AccessibleObject.setAccessible(fromFields, true);

      前面讲述了如何用Java反射机制操作一个类的方法和属性,下面再通过一个实例讲述如何在运行时创建类的一个对象:

复制代码
 1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Field;
4
5 /**
6 * Java 反射之属性练习。
7 *
8 * @author Wanggc
9 */
10 public class ReflectionTest {
11 public static void main(String[] args) throws Exception {
12 // 建立学生对象
13 Student student = new Student();
14 // 为学生对象赋值
15 student.setStuName("Wanggc");
16 student.setStuAge(24);
17 // 建立拷贝目标对象
18 Student destStudent = (Student) copyBean(student);
19 // 输出拷贝结果
20 System.out.println(destStudent.getStuName() + ":"
21 + destStudent.getStuAge());
22 }
23
24 /**
25 * 拷贝学生对象信息。
26 *
27 * @param from
28 * 拷贝源对象
29 * @param dest
30 * 拷贝目标对象
31 * @throws Exception
32 * 例外
33 */
34 private static Object copyBean(Object from) throws Exception {
35 // 取得拷贝源对象的Class对象
36 Class<?> fromClass = from.getClass();
37 // 取得拷贝源对象的属性列表
38 Field[] fromFields = fromClass.getDeclaredFields();
39 // 取得拷贝目标对象的Class对象
40 Object ints = fromClass.newInstance();
41 for (Field fromField : fromFields) {
42 // 设置属性的可访问性
43 fromField.setAccessible(true);
44 // 将拷贝源对象的属性的值赋给拷贝目标对象相应的属性
45 fromField.set(ints, fromField.get(from));
46 }
47
48 return ints;
49 }
50 }
51
52 /**
53 * 学生类。
54 */
55 class Student {
56 /** 姓名 */
57 private String stuName;
58 /** 年龄 */
59 private int stuAge;
60
61 /**
62 * 获取学生姓名。
63 *
64 * @return 学生姓名
65 */
66 public String getStuName() {
67 return stuName;
68 }
69
70 /**
71 * 设置学生姓名
72 *
73 * @param stuName
74 * 学生姓名
75 */
76 public void setStuName(String stuName) {
77 this.stuName = stuName;
78 }
79
80 /**
81 * 获取学生年龄
82 *
83 * @return 学生年龄
84 */
85 public int getStuAge() {
86 return stuAge;
87 }
88
89 /**
90 * 设置学生年龄
91 *
92 * @param stuAge
93 * 学生年龄
94 */
95 public void setStuAge(int stuAge) {
96 this.stuAge = stuAge;
97 }
98 }
复制代码

      此例和上例运行的结果是相同的。但是copyBean方法返回的对象不再是外面传入的,而是由方法内部产生的,如第40行代码所示。注意:Class的newInstance方法,只能创建只包含无参数的构造函数的类,如果某类只有带参数的构造函数,那么就要使用另外一种方式:fromClass.getDeclaredConstructor(int.class,String.class).newInstance(24,"wanggc");

      至此,Java反射机制的常用机能(运行时调用对象的方法、类属性的使用、创类类的对象)已经介绍完了。

      补充:在获得类的方法、属性、构造函数时,会有getXXX和getgetDeclaredXXX两种对应的方法。之间的区别在于前者返回的是访问权限为public的方法和属性,包括父类中的;但后者返回的是所有访问权限的方法和属性,不包括父类的。

分享到:
评论

相关推荐

    java反射 java反射 java反射java反射

    Java反射是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类的对象。在Java中,反射机制提供了强大的能力,包括在运行时检查类的结构、创建对象实例、调用方法以及访问和修改字段值。...

    java反射,获取所有属性、方法以及List集合类

    Java反射是Java编程语言中的一个强大工具,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建对象、获取类...

    JAVA反射机制的入门代码

    Java反射机制是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在处理元数据、创建对象、调用私有方法...

    JAVA 反射机制应用

    Java反射机制是Java语言提供的一种强大功能,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类是java.lang.Class,它代表了运行时的类信息。通过Class对象,我们...

    java 反射得到某个方法

    在本文中,我们将深入探讨如何使用Java反射来获取并执行某个特定的方法。 首先,我们需要了解Java反射的基本概念。`java.lang.Class`类是反射的核心,它代表了Java中的每一个类。我们可以通过以下方式获取到一个...

    Java反射性能测试分析

    ### Java反射性能测试分析 #### 引言 Java反射机制是Java编程语言中一个强大的特性,它允许程序在运行时动态地访问、检测和修改类、接口、字段和方法等对象。然而,反射操作通常会引入额外的开销,这在性能敏感的...

    Java反射机制总结

    ### Java反射机制总结 #### 反射的概念与起源 反射的概念最早由Smith于1982年提出,指的是程序能够访问、检测并修改其自身状态或行为的能力。这一概念的提出迅速引起了计算机科学领域的广泛关注,并在之后的研究中...

    Java反射经典实例

    Java反射是Java编程语言中的一个强大特性,它允许运行时的程序访问并操作类、接口、字段和方法等信息,即使这些信息在编译时并未明确知晓。在Java中,反射通常通过`java.lang.Class`类和相关的API来实现。本实例将...

    反射实例-JAVA反射机制

    ### 反射实例—JAVA反射机制 #### 一、反射概念及原理 反射在计算机科学领域,特别是程序设计中,是指程序有能力访问、检测和修改其自身的结构和行为。这一概念最早由Smith于1982年提出,并迅速应用于各种编程语言...

    java反射.pdf

    ### Java反射机制详解 #### 一、什么是Java反射? Java反射是Java编程语言的一个特性,它允许运行时检查和操作程序结构(类、字段、方法等)。反射的主要用途包括但不限于:动态实例化对象、访问私有成员、调用...

    java 反射 调用私有方法(有参数私有方法)获取私有属性值

    Java反射是Java语言提供的一种强大的动态类型特性,它允许程序在运行时检查类、接口、字段和方法的信息,并且能够动态地创建对象和调用方法。这个能力使得开发者可以突破静态类型的束缚,实现一些在编译时期无法完成...

    java反射源代码

    Java反射是Java编程语言中的一个强大特性,它允许在运行时检查类、接口、字段和方法的信息,并且能够在运行时动态地创建对象和调用方法。这个特性使得Java具有高度的灵活性,尤其在处理框架、插件系统以及元数据驱动...

    java 反射机制例子

    ### Java反射机制详解 #### 一、反射的基本概念与历史背景 反射的概念最早由Smith在1982年提出,其核心思想是程序有能力访问、检测甚至修改自身的状态和行为。这种能力一经提出,迅速成为了计算机科学领域的研究...

    java反射获取所有属性,获取所有get方法,包括子类父类

    Java反射是Java编程语言中的一个强大工具,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射主要用于在运行时分析类和对象,包括访问私有成员、调用私有方法、创建动态代理等。...

    利用java反射将json字符串转成对象.zip

    Java反射是Java编程语言中的一个强大工具,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在给定的“利用java反射将json字符串转成对象”的主题中,我们将深入探讨如何借助反射机制将JSON...

    Java反射机制Demo

    ### Java反射机制详解 #### 一、什么是Java反射机制? Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的...

    北大青鸟java反射机制

    Java反射机制是Java编程语言中的一个强大工具,它允许程序在运行时检查并操作类、接口、字段和方法等对象。在"北大青鸟java反射机制"的学习资料中,我们将会深入探讨这一核心特性。 首先,我们要理解反射的核心概念...

    java反射深入剖析(推荐)

    Java反射是Java语言提供的一种强大的机制,它允许我们在运行时检查和操作类、接口、字段和方法等。本文将深入剖析Java反射的概念及其在实际开发中的应用。 首先,我们需要了解,反射的核心在于`java.lang.Class`类...

Global site tag (gtag.js) - Google Analytics