JAVA基础(12)——反射

来源:互联网 发布:白蜡杆 淘宝 编辑:程序博客网 时间:2024/05/22 06:27

JAVA基础系列规划:

  • JAVA基础(1)——基本概念
  • JAVA基础(2)——数据类型
  • JAVA基础(3)——容器(1)——常用容器分类
  • JAVA基础(4)——容器(2)——普通容器
  • JAVA基础(5)——并发(1)——总体认识
  • JAVA基础(6)——并发(2)——原子
  • JAVA基础(7)——并发(3)——锁机制
  • JAVA基础(8)——并发(4)——线程池
  • JAVA基础(9)——容器(3)——并发容器
  • JAVA基础(10)——IO、NIO
  • JAVA基础(11)——泛型
  • JAVA基础(12)——反射
  • JAVA基础(13)——序列化
  • JAVA基础(14)——网络编程

个人把java反射理解为一种框架,在框架内可以通过名称来控制类结构及其对象。而框架的基础就是java.lang.Class类和java.lang.reflect包中的Field、Constructor、Method、Array类。

Class类的实例表示正在运行的Java应用程序中的类和接口,保存它们的运行时类型标识信息。因此,它是java反射的开始,只有获得Class类的对象,才能通过这个对象获取其他相关信息。

获取一个类对象的Class,有三种方式:

Class classInstance = Person.class; //类型名.class获取该类型对应的Class对象Class classInstance = Class.forName("Person"); //Class类的forName()静态方法获得与字符串对应的Class对象Class classInstance = new Person().getClass(); //调用Object类对象的getClass()方法类得到Class对象

1. 获取数据结构

从Class开始,可以获取classInstance所关联的类的类名:

classInstance.getName(); //获得类的完整名字

不仅如此,类里面的所有东西都可以获取,Field、Constructor、Method,分别对应着类的成员变量、构造方法和成员方法。

Field[] fields = classInstance.getFields(); //获得类的public类型的属性

这样就获取了类的属性,但注意,只是public类型的属性,要获取类的所有属性,需要

Field[] fields = classInstance.getDeclaredFields(); //获得类的所有属性

要通过属性名称来获取类属性,就需要下面的方法了:

Field field = classInstance.getField("profession"); //public类型属性适用Field field = classInstance.getDeclaredFields("profession"); //所有类型属性均适用

获取构造方法类似:

Constructor[] cs = classInstance.getConstructors(); //获得类的public类型的构造方法Constructor[] cs2 = classInstance.getDeclaredConstructors(); //获得类的所有构造方法Class parameterTypes[] = { java.lang.String.class }; //parameterTypes参数指定构造方法的参数类型Constructor c = classInstance.getConstructor(parameterTypes); //public类型构造方法适用Constructor c2 = classInstance.getDeclaredConstructor(parameterTypes);//所有类型构造方法适用Constructor c3 = classInstance.getEnclosingConstructor(); //获取本地或匿名类Constructor对象

获取成员方法类似:

Method[] ms = classInstance.getMethods();//获得类的public类型的方法Method[] ms2 = classInstance.getDeclaredMethods();//获得类的所有方法String methodName = "setName";Class methodParaTypes[] = { java.lang.String.class }; //methodParaTypes参数指定方法的参数类型Method m2 = classInstance.getMethod(methodName, methodParaTypes);//public类型构造方法适用Method m3 = classInstance.getDeclaredMethod(methodName, methodParaTypes);//所有类型构造方法适用

2. 实例化对象

不仅可以获取类的内部结构,还可以实例化出对象,方法为:

Person p = (Person)classInstance.getConstructor(new Class[] {}).newInstance(new Object[] {}); //通过类的不带参数的构造方法创建类对象

上句是通过类的不带参数的构造方法创建类对象,还可以用另一种表达:

Person p2 = (Person)classInstance.newInstance(); //通过类的不带参数的构造方法创建类对象

对于带参数的构造方法,就只有一条路了:

Person p3 = (Person)classInstance.getConstructor(new Class[] {java.lang.String.class}).newInstance(new String[] {"best"}); //通过类的带参数的构造方法创建类对象。

3. 调用实例化对象方法

使用Method,传递参数,隐式调用执行对象的方法:

String methodName2 = "getName";Method m4 = classInstance.getMethod(methodName2);Object value = m4.invoke(new Person(), new Object[] {});

4. 举个栗子

仿commons-beanutils中复制对象,这是一个运行时复制对象的过程。

import java.lang.reflect.Field;import java.lang.reflect.Method;public class BeanHelper {    public static Object copy(Object object) throws Exception {        Class classInfo = object.getClass();        Object objectCopy = classInfo.newInstance();        Field fields[] = classInfo.getDeclaredFields();        for(int i=0; i<fields.length; i++) {            Field field = fields[i];            String fieldName = field.getName();            String firstLetter = fieldName.substring(0, 1).toUpperCase();            String getMethodName = "get" + firstLetter + fieldName.substring(1);            String setMethodName = "set" + firstLetter + fieldName.substring(1);            Method getMethod = classInfo.getMethod(getMethodName, new Class[] {});            Method setMethod = classInfo.getMethod(setMethodName, new Class[] { field.getType() });            Object value = getMethod.invoke(object, new Object[] {});            setMethod.invoke(objectCopy, new Object[] { value });        }        return objectCopy;    }}

小测一下:

public class Main {    public static void main(String[] args) throws Exception {        Person p = new Person();        Person p2 = (Person)BeanHelper.copy(p);        System.out.println(p2.getName());    }}

5. 反射与动态代理

在企业应用高级框架中大量用到代理模式,其原理主要就是应用到反射。

详见代理http://www.blogjava.net/baoyaer/articles/84080.html

6. 附

public class Person {    private String name;    private String sex;    private String age;    public Person() {        name = "default";        sex = "male";        age = "25";    }    public Person(String name) {        this.name = name;        sex = "male";        age = "25";    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }    public String getAge() {        return age;    }    public void setAge(String age) {        this.age = age;    }    public void walk(float length) {        System.out.println("walk " + length);    }}

7. 参考文档

Java反射机制深入研究 JAVA的内省(introspector)与反射(reflection)

0 0