国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > php教程 > Java 反射机制浅析

Java 反射机制浅析

来源:程序员人生   发布时间:2017-02-05 13:52:56 阅读次数:2551次

学习Java的同学注意了!!! 
学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码:183993990  我们1起学Java!


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

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

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

      首先看1个简单的例子,通过这个例子来理解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时,会输出以下结果

复制代码
public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public int java.lang.String.hashCode()
public int java.lang.String.compareTo(java.lang.String)
public int java.lang.String.compareTo(java.lang.Object)
public int java.lang.String.indexOf(int)
public int java.lang.String.indexOf(int,int)
public int java.lang.String.indexOf(java.lang.String)
public int java.lang.String.indexOf(java.lang.String,int)
public static java.lang.String java.lang.String.valueOf(int)
public static java.lang.String java.lang.String.valueOf(char)
public static java.lang.String java.lang.String.valueOf(boolean)
public static java.lang.String java.lang.String.valueOf(float)
public static java.lang.String java.lang.String.valueOf(char[],int,int)
public static java.lang.String java.lang.String.valueOf(double)
public static java.lang.String java.lang.String.valueOf(char[])
public static java.lang.String java.lang.String.valueOf(java.lang.Object)
public static java.lang.String java.lang.String.valueOf(long)
public char java.lang.String.charAt(int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int)
public int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
public boolean java.lang.String.contains(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.CharSequence)
public boolean java.lang.String.contentEquals(java.lang.StringBuffer)
public static java.lang.String java.lang.String.copyValueOf(char[])
public static java.lang.String java.lang.String.copyValueOf(char[],int,int)
public boolean java.lang.String.endsWith(java.lang.String)
public boolean java.lang.String.equalsIgnoreCase(java.lang.String)
public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
public void java.lang.String.getBytes(int,int,byte[],int)
public byte[] java.lang.String.getBytes()
public byte[] java.lang.String.getBytes(java.nio.charset.Charset)
public void java.lang.String.getChars(int,int,char[],int)
public native java.lang.String java.lang.String.intern()
public boolean java.lang.String.isEmpty()
public int java.lang.String.lastIndexOf(java.lang.String)
public int java.lang.String.lastIndexOf(int,int)
public int java.lang.String.lastIndexOf(int)
public int java.lang.String.lastIndexOf(java.lang.String,int)
public int java.lang.String.length()
public boolean java.lang.String.matches(java.lang.String)
public int java.lang.String.offsetByCodePoints(int,int)
public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
public boolean java.lang.String.regionMatches(int,java.lang.String,int,int)
public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,char)
public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,int)
public boolean java.lang.String.startsWith(java.lang.String)
public boolean java.lang.String.startsWith(java.lang.String,int)
public java.lang.CharSequence java.lang.String.subSequence(int,int)
public java.lang.String java.lang.String.substring(int)
public java.lang.String java.lang.String.substring(int,int)
public char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
复制代码

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

      使用java的反射机制,1般需要遵守3步:

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

     Java运行的时候,某个类不管生成多少个对象,他们都会对应同1个Class对象,它表示正在运行程序中的类和接口。如何获得操作类的Class对象,经常使用的有3种方式:

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

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

复制代码
 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反射的第1步就是取得这个Class对象,如代码14行。固然,每一个类的方法也必有1个Method对象与之对应。要通过反射的方式调用这个方法,就要首先取得这个方法的Method对象,如代码16行,然后用Method对象反过来调用这个方法,如代码18行。注意16行getMethod方法的第1个参数是方法名,第2个是此方法的参数类型,如果是多个参数,接着添加参数就能够了,由于getMethod是可变参数方法。履行18行代码的invoke方法,其实也就是履行show方法,注意invoke的第1个参数,是DisPlay类的1个对象,也就是调用DisPlay类哪一个对象的show方法,第2个参数是给show方法传递的参数。类型和个数1定要与16行的getMethod方法1直。

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

复制代码
  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 // 设置属性的可访问性
生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生