最近总是用到java反射机制,一直不知道其中的原理,通过查阅API以及网络博客,有了一个初步认识,今天抽出时间整理一下,一下示例只是浅谈java反射机制,更深入的学习放在后面。
定义:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
功能:
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
Class:
众所周知Java有个Object 类,是所有Java 类的继承根源,其内声明了数个应该在所有Java 类中被改写的方法:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class 对象。
Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。
Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。如果您想借由“修改Java标准库源码”来观察Class 对象的实际生成时机(例如在Class的constructor内添加一个println()),这样是行不通的!因为Class并没有public constructor。
说了一堆概念,下面说一下本文的具体功能实现:
1,实体类
Person.java
package com.superb.reflect;
/**
* 父类--> 人类
* @author superb
*
*/
public class Person {
/** 姓名 */
private String name;
/** 年龄 */
private int age;
/** 性别 */
private String sex;
/** 手机号 */
private String phone;
public Person() {
logger("无参构造方法");
}
/**
* 构造方法
* @param name
* @param age
*/
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
logger("有参构造方法");
}
/**
* 吃方法
* @param date
* @param food
*/
public void eat(String name, String food){
logger(name+"开始吃"+food);
}
/**
*
* @param msg
*/
public void logger(String msg){
System.out.println("----->"+msg);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}package com.superb.reflect;
/**
* 子类-->学生类
* @author superb
*
*/
public class Student extends Person{
/** 学校 */
private String stuSchool;
/** 班级 */
private String stuClass;
public Student() {
super();
}
public Student(String stuSchool, String stuClass) {
super();
this.stuSchool = stuSchool;
this.stuClass = stuClass;
}
public String getStuSchool() {
return stuSchool;
}
public void setStuSchool(String stuSchool) {
this.stuSchool = stuSchool;
}
public String getStuClass() {
return stuClass;
}
public void setStuClass(String stuClass) {
this.stuClass = stuClass;
}
}
2,测试类(代码中有详细注解)
package com.superb.junit;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.junit.Test;
import com.superb.reflect.Person;
import com.superb.reflect.Student;
import junit.framework.TestCase;
/**
* 测试类
* @author superb
*
*/
public class TestReflect extends TestCase{
/**
* 通过getCalss方法获取类
*/
@Test
public void testGetClazz() throws Exception{
Class
clazz = new Person().getClass();
System.out.println(clazz.getTypeName());
}
/**
* 通过.class属性获取类
* @throws Exception
*/
@Test
public void testClass() throws Exception{
Class
clazz = Student.class;
System.out.println(clazz.getTypeName());
}
/**
* 通过static method Class.forName() 获取类
* @throws Exception
*/
@Test
public void testClazzName() throws Exception{
Class
clazz = Class.forName("com.superb.reflect.Student");//类的完整路径
System.out.println(clazz.getTypeName());
}
/**
*可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。
*JAVA 的Class
类提供了几个方法获取类的属性。
*/
@Test
public void testGetClazzField() throws Exception{
//获取类
Class
clazz = Student.class;
//获取所有属性
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
System.out.println("属性名:"+f.getName()+";属性类型:"+f.getType().getSimpleName());
}
//获取特定属性
Field field = clazz.getDeclaredField("stuSchool");
System.out.println("属性名:"+field.getName()+";属性类型:"+field.getType().getSimpleName());
//实例化对象
Object obj = clazz.newInstance();
//打破封装类
field.setAccessible(true);
//给属性赋值
field.set(obj, "长江师范学院");
System.out.println(field.get(obj));
System.out.println(field.isEnumConstant());//属性是否是枚举
}
/**
* java通过反射机制得到类对象的方法,并可调用该方法执行操作
* @throws Exception
*/
@Test
public void testGetClazzMethod() throws Exception{
Class
clazz = Person.class;
//获取所有方法
Method[] methods = clazz.getDeclaredMethods();
for(Method m : methods){
System.out.println("方法名:"+m.getName()+",方法类型:"+m.getReturnType());
if(m.getName().equals("eat")){
Parameter[] params = m.getParameters();
for(Parameter param :params){
System.out.println("参数类型:"+ param.getParameterizedType());
}
//对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。我们这里调用Person类总的eat方法,
m.invoke(clazz.newInstance(), "小明","苹果");
}
}
}
/**
* 通过java反射获得类的构造方法,然后调用该构造器创建该类的一个实例
* @throws Exception
*/
@SuppressWarnings("rawtypes")
@Test
public void testGetConstructor()throws Exception{
Class
clazz = Person.class;
// 使用getConstructors获取构造器
Constructor[] constructor1 = clazz.getConstructors();
for(Constructor
c : constructor1){
System.out.println(c.getName());
}
// 使用getDeclaredConstructors获取构造器
Constructor[] constructor2 = clazz.getDeclaredConstructors();
for(Constructor
c : constructor2){
System.out.println(c.getName());
}
}
}
总结:
下一期将深入讲解java反射机制;