目前非常多的开源框架的工作核心和底层实现原理都是基于反射来工作的。我这边也是闲来无事,公司那边等着走流程签合同,就自己看着JDK的API文档,并结合以前用过的一点知识,做了下反射的简单事例。
首先反射的具体功能是发现类的方法、属性、构造器(包含私有属性、方法和构造器)。网上众多的所谓动态代理的实现大多也是通过反射来实现的。
涉及Java包主要为java.lang.Class,java.lang.reflect,我的JDK版本是1.6的。
由于时间有限,我这次也是浅尝,下次在进一步研究和更新。
这里只有两个类:为了好看,我将测试方法和发现的机制放到了同一个类(ReflectDemo )中如下:
package com.xiaoyun.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射机制学习
*
* @author XiaoYun 2013-07-10
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Person person = new Person(1,1,1.0,"中国人", false);
reflect(person);
}
/**
* 反射功能
* 用于发现 obj的类型
* obj的方法
* obj的属性
* obj的构造器
* @param obj 用户被发现的对象
*/
public static void reflect(Object obj) {
Class cls = obj.getClass();
//发现该类的类型
String clsName = cls.getSimpleName();
System.out.println("类名:" + clsName);
//发现该类的属性
//返回该对象所表示的类或接口中声明的所有字段
Field[] allFields = cls.getDeclaredFields();
//返回该对象表示的类或接口中声明的公共字段
//Field[] unPrivateFields = cls.getFields();
StringBuilder fields = new StringBuilder(150);
fields.append("声明的属性:");
//组装打印到控制台的字段
for (Field field : allFields) {
Annotation[] annotations = field.getAnnotations();
fields.append(field.getName()).append(",").append(field.getType().getName()).append(",").
append(annotations.length).append("\n");
}
System.out.println(fields.toString());
//发现该类的方法(包含私有方法)
Method[] methods = cls.getDeclaredMethods();
//组装打印到控制台的方法描述
StringBuilder methodsStr = new StringBuilder(100);
methodsStr.append("方法的声明:");
for (Method method : methods) {
methodsStr.append(method.getName()).append(",");
//形参类型
Class[] clazz = method.getParameterTypes();
for (Class c : clazz) {
System.out.println(c.getSimpleName());
}
}
methodsStr.deleteCharAt(methodsStr.lastIndexOf(","));
System.out.println(methodsStr.toString());
//发现该类的构造器
//返回该对象表示的类的所有公共的构造方法
Constructor[] unPrivateConstructors = cls.getConstructors();
//发现该对象表示的类所声明的所有的构造方法
Constructor[] allConstructors = cls.getDeclaredConstructors();
//组装打印到控制台的构造器描述
StringBuilder constructors = new StringBuilder(150);
constructors.append("构造器:");
for (Constructor constructor : allConstructors) {
constructors.append(constructor.getName()).append(",");
Class[] types = constructor.getParameterTypes();
for (Class class1 : types) {
constructors.append(class1.getName()).append("\n");
}
}
constructors.deleteCharAt(constructors.lastIndexOf(","));
System.out.println(constructors.toString());
}
}
测试你也可以使用Class.forName("java.lang.String")等来获取对象的方法和属性,我这里是使用的自己又创建了一个Pojo类(Person):
package com.xiaoyun.reflect;
/**
* 人实体类
*
* @author XiaoYun 2013-07-10
*/
public class Person {
private static Person instance = new Person();
/** 年龄 */
private Integer age;
/** 身高*/
private Integer height;
/** 体重 */
private double weight;
/** 描述 */
private String desc;
/** 婚否 */
private boolean isMarry;
private Person() {
}
public Person(int age, int height, double weight, String desc,
boolean isMarry) {
super();
this.age = age;
this.height = height;
this.weight = weight;
this.desc = desc;
this.isMarry = isMarry;
}
public static Person getInstance() {
return instance;
}
//说明,这里是为了测试反射机制能发现私有方法而对get方法做的修改
private Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getHeight() {
return height;
}
//说明,这里是为了测试反射机制能发现私有方法而对get方法做的修改
private void setHeight(Integer height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public boolean isMarry() {
return isMarry;
}
public void setMarry(boolean isMarry) {
this.isMarry = isMarry;
}
}
代码在我的电脑上运行过,完全正常,代码可以直接粘贴,只不过打印出来的属性的类别,Integer打印出来的是int,boolean是boolean,String是java.lang.String,是正常的,我认为可能是JDK编译的时候还是把Integer类型当做简单类型来编译的,所以打印出来的没有在lang包中。
你也可以在获取该实例的属性、方法后,调用该方法。
关于动态代理的具体实现,下次在发布。这次的重点是掌握反射机制的原理。即java.lang.Class包和java.lang.reflect.Field,java.lang.reflect.Method,java.lang.reflect.Construct的使用。
下次将对JDK或CGLIB对动态代理的实现原理做演示和讲解。
初次发布自己写的东西,不合适和不完整的地方欢迎各位同行和前辈们批评指正。谢谢
下次
首先反射的具体功能是发现类的方法、属性、构造器(包含私有属性、方法和构造器)。网上众多的所谓动态代理的实现大多也是通过反射来实现的。
涉及Java包主要为java.lang.Class,java.lang.reflect,我的JDK版本是1.6的。
由于时间有限,我这次也是浅尝,下次在进一步研究和更新。
这里只有两个类:为了好看,我将测试方法和发现的机制放到了同一个类(ReflectDemo )中如下:
package com.xiaoyun.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 反射机制学习
*
* @author XiaoYun 2013-07-10
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
Person person = new Person(1,1,1.0,"中国人", false);
reflect(person);
}
/**
* 反射功能
* 用于发现 obj的类型
* obj的方法
* obj的属性
* obj的构造器
* @param obj 用户被发现的对象
*/
public static void reflect(Object obj) {
Class cls = obj.getClass();
//发现该类的类型
String clsName = cls.getSimpleName();
System.out.println("类名:" + clsName);
//发现该类的属性
//返回该对象所表示的类或接口中声明的所有字段
Field[] allFields = cls.getDeclaredFields();
//返回该对象表示的类或接口中声明的公共字段
//Field[] unPrivateFields = cls.getFields();
StringBuilder fields = new StringBuilder(150);
fields.append("声明的属性:");
//组装打印到控制台的字段
for (Field field : allFields) {
Annotation[] annotations = field.getAnnotations();
fields.append(field.getName()).append(",").append(field.getType().getName()).append(",").
append(annotations.length).append("\n");
}
System.out.println(fields.toString());
//发现该类的方法(包含私有方法)
Method[] methods = cls.getDeclaredMethods();
//组装打印到控制台的方法描述
StringBuilder methodsStr = new StringBuilder(100);
methodsStr.append("方法的声明:");
for (Method method : methods) {
methodsStr.append(method.getName()).append(",");
//形参类型
Class[] clazz = method.getParameterTypes();
for (Class c : clazz) {
System.out.println(c.getSimpleName());
}
}
methodsStr.deleteCharAt(methodsStr.lastIndexOf(","));
System.out.println(methodsStr.toString());
//发现该类的构造器
//返回该对象表示的类的所有公共的构造方法
Constructor[] unPrivateConstructors = cls.getConstructors();
//发现该对象表示的类所声明的所有的构造方法
Constructor[] allConstructors = cls.getDeclaredConstructors();
//组装打印到控制台的构造器描述
StringBuilder constructors = new StringBuilder(150);
constructors.append("构造器:");
for (Constructor constructor : allConstructors) {
constructors.append(constructor.getName()).append(",");
Class[] types = constructor.getParameterTypes();
for (Class class1 : types) {
constructors.append(class1.getName()).append("\n");
}
}
constructors.deleteCharAt(constructors.lastIndexOf(","));
System.out.println(constructors.toString());
}
}
测试你也可以使用Class.forName("java.lang.String")等来获取对象的方法和属性,我这里是使用的自己又创建了一个Pojo类(Person):
package com.xiaoyun.reflect;
/**
* 人实体类
*
* @author XiaoYun 2013-07-10
*/
public class Person {
private static Person instance = new Person();
/** 年龄 */
private Integer age;
/** 身高*/
private Integer height;
/** 体重 */
private double weight;
/** 描述 */
private String desc;
/** 婚否 */
private boolean isMarry;
private Person() {
}
public Person(int age, int height, double weight, String desc,
boolean isMarry) {
super();
this.age = age;
this.height = height;
this.weight = weight;
this.desc = desc;
this.isMarry = isMarry;
}
public static Person getInstance() {
return instance;
}
//说明,这里是为了测试反射机制能发现私有方法而对get方法做的修改
private Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getHeight() {
return height;
}
//说明,这里是为了测试反射机制能发现私有方法而对get方法做的修改
private void setHeight(Integer height) {
this.height = height;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public boolean isMarry() {
return isMarry;
}
public void setMarry(boolean isMarry) {
this.isMarry = isMarry;
}
}
代码在我的电脑上运行过,完全正常,代码可以直接粘贴,只不过打印出来的属性的类别,Integer打印出来的是int,boolean是boolean,String是java.lang.String,是正常的,我认为可能是JDK编译的时候还是把Integer类型当做简单类型来编译的,所以打印出来的没有在lang包中。
你也可以在获取该实例的属性、方法后,调用该方法。
关于动态代理的具体实现,下次在发布。这次的重点是掌握反射机制的原理。即java.lang.Class包和java.lang.reflect.Field,java.lang.reflect.Method,java.lang.reflect.Construct的使用。
下次将对JDK或CGLIB对动态代理的实现原理做演示和讲解。
初次发布自己写的东西,不合适和不完整的地方欢迎各位同行和前辈们批评指正。谢谢
下次