JAVA Reflect反射详解

1.什么是java反射

java的反射机制是指在运行状态中,

        对于任意一个类,都能知道这个类的所有属性和方法;

        对于任意一个对象,都能够调用它的任意一个属性和方法;

        这种动态获取的类的信息,和动态调用对象的方法的功能就是反射机制。

2.反射的作用

        在运行时,构造任意一个类的对象

        在运行时,判断任意一个类的完整结构,比如属性,方法,内部类,实现接口等

        在运行时,判断任意一个对象所属的类

        在运行时,调用任意一个对象的属性和方法

        在运行时,生成动态代理

3.关键类


Class类是反射类的基础,在java.lang包下,有四种方式可以获取Class类对象

Field,Method,Constructor 都在java.lang.reflect包下

Field是获取Class对象中的属性

Method是获取Class对象中的方法(不包含构造方法)

Construct是获取Class对象中的构造函数

4.测试代码

四种获取Class类的方法:

		Person p = new Person();
		// 方法一 : 调用运行时类的.class属性
		Class c1 = Person.class;
		System.out.println("方法一 : 调用运行时类的.class属性: "+c1.toString());
		
		// 方法二 : 通过运行时类的对象,调用getClass()方法
		Class c2 = p.getClass();
		System.out.println("方法二 : 通过运行时类的对象,调用getClass()方法: "+c2.toString());
		
		// 方法三 : 调用Class的静态方法forName
		Class c3 = Class.forName("reflect.Person");
		System.out.println("方法三 : 调用Class的静态方法forName: "+c3.toString());
		
		// 方法四 :通过类的加载器
		ClassLoader classLoader = Person.class.getClassLoader();
		Class c4 = classLoader.loadClass("reflect.Person");
		System.out.println("方法四 :通过类的加载器: "+c4.toString());

运行结果是:

方法一 : 调用运行时类的.class属性: class reflect.Person
方法二 : 通过运行时类的对象,调用getClass()方法: class reflect.Person
方法三 : 调用Class的静态方法forName: class reflect.Person
方法四 :通过类的加载器: class reflect.Person

获取Class中的构造函数:

	    System.out.println("getConstructors为获取类的public的构造方法 ");
	    Constructor[] constructors1 = c1.getConstructors();
	    for(int i=0;i<constructors1.length;i++){
	        System.out.println("constructors ["+i+"] :"+constructors1[i]);
	    }
		Class<? extends Object> c1 = Person.class;
		
		//调用指定的构造器创建运行时类的对象
	    //我们指定public类型的构造方法Person(String name)来创建对象
	    Constructor<?> constructor = c1.getDeclaredConstructor(String.class);
	    Person person = (Person) constructor.newInstance("xl");
	    System.out.println("调用指定的构造器(public)创建运行时类的对象 --person: "+person);	    
	    
	    //我们指定private类型的构造方法Person(String name)来创建对象
	    constructor = c1.getDeclaredConstructor(String.class,String.class);
	    constructor.setAccessible(true);
	    person = (Person) constructor.newInstance("xl2","15");
	    System.out.println("调用指定的构造器(private)创建运行时类的对象 --person: "+person);

运行结果是:

getConstructors为获取类的public的构造方法 
constructors [0] :public reflect.Person(java.lang.String)
constructors [1] :public reflect.Person()
调用指定的构造器(public)创建运行时类的对象 --person: [name : xl ][age : null]
调用指定的构造器(private)创建运行时类的对象 --person: [name : xl2 ][age : 15]

获取Class中全部Method:

		Person person = new Person();
		Class<? extends Object> c1 = person.getClass();
		
		//getMethods此方法为获取类的public方法,包括父类的public方法
	    System.out.println("getMethods此方法为获取类的public方法,包括父类的public方法 ");
	    Method[] method1 = c1.getMethods();      
	    for(int i=0;i<method1.length;i++){
	        System.out.println("method1 ["+i+"] :"+method1[i]);
	    }

	    //getDeclaredMethods此方法为获取类本身声明的所有方法,包括private
	    System.out.println("getDeclaredMethods此方法为获取类本身声明的所有方法,包括private ");
	    Method[] method2 = c1.getDeclaredMethods();      
	    for(int i=0;i<method2.length;i++){
	        System.out.println("method2 ["+i+"] :"+method2[i]);
	    }
	    
	    //1.对private类型的方法进行操作
	    System.out.println("getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName(私有)方法为例:");
	    Method m1 = c1.getDeclaredMethod("setName", String.class);
	    m1.setAccessible(true);
	    System.out.println("修改前的person:"+person);
	    m1.invoke(person, "xl");
	    System.out.println("修改后的person:"+person);

运行结果是:

getMethods此方法为获取类的public方法,包括父类的public方法 
method1 [0] :public java.lang.String reflect.Person.toString()
method1 [1] :public java.lang.String reflect.Person.getName()
method1 [2] :public void reflect.Person.setName(java.lang.String)
method1 [3] :public void reflect.Person.setAge(java.lang.String)
method1 [4] :public java.lang.String reflect.Person.getAge()
method1 [5] :public final void java.lang.Object.wait() throws java.lang.InterruptedException
method1 [6] :public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method1 [7] :public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method1 [8] :public boolean java.lang.Object.equals(java.lang.Object)
method1 [9] :public native int java.lang.Object.hashCode()
method1 [10] :public final native java.lang.Class java.lang.Object.getClass()
method1 [11] :public final native void java.lang.Object.notify()
method1 [12] :public final native void java.lang.Object.notifyAll()
getDeclaredMethods此方法为获取类本身声明的所有方法,包括private 
method2 [0] :public java.lang.String reflect.Person.toString()
method2 [1] :public java.lang.String reflect.Person.getName()
method2 [2] :public void reflect.Person.setName(java.lang.String)
method2 [3] :void reflect.Person.getSex()
method2 [4] :public void reflect.Person.setAge(java.lang.String)
method2 [5] :public java.lang.String reflect.Person.getAge()
getDeclaredMethod 方法获取类本身声明的方法,包括private类型的方法,以setName(私有)方法为例:
修改前的person:[name : null ][age : null]
修改后的person:[name : xl ][age : null]

获取Class类中Field

		Class<? extends Object> c1 = Person.class;

	    System.out.println("getFields此方法为获取类的public属性,包括父类的public属性 ");
	    Field[] field1 = c1.getFields();     
	    for(int i=0;i<field1.length;i++){
	        System.out.println("field1 ["+i+"] :"+field1[i]);
	    }
	    
	    System.out.println("getDeclaredFields此方法为获取类的本身声明的所有属性,包括private ");
	    Field[] field2 = c1.getDeclaredFields();     
	    for(int i=0;i<field2.length;i++){
	        System.out.println("field2 ["+i+"] :"+field2[i]);
	    }

运行结果是:

getFields此方法为获取类的public属性,包括父类的public属性 
field1 [0] :public java.lang.String reflect.Person.age
getDeclaredFields此方法为获取类的本身声明的所有属性,包括private 
field2 [0] :private java.lang.String reflect.Person.name
field2 [1] :public java.lang.String reflect.Person.age

对Field进行处理:

	    Person person = new Person("zj");
	    Class<? extends Object> c1 = person.getClass();
	    
	    System.out.println("对public类型的属性进行操作,以类本身的private属性name为例");
	    Field f1 = c1.getDeclaredField("name");
	    f1.setAccessible(true);
	    String name = (String)f1.get(person);
	    System.out.println("修改前person对象name:"+name);
	    
	    f1.set(person, "xl");
	    name = (String)f1.get(person);
	    System.out.println("修改后person对象的name:"+name);

运行结果是:

对public类型的属性进行操作,以类本身的private属性name为例
修改前person对象name:zj
修改后person对象的name:xl
还有一些对内部类、接口进行的一些操作,这里就不一一列举了。

5.用例:重写Object的toString方法

public class Person {
	
	private String name;
	
	private String age;

	public Person(String name, String age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		try {
			// 1.获取Class类
			Class<? extends Object> clazz = this.getClass();
			// 2.获取全部属性
			Field [] fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				String fieldName = field.getName();
				// 3.除去序列化属性
				if ("serialVersionUID".equals(fieldName)) {
					continue;
				}
				// 4.拼接方法名
				String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1, fieldName.length());
				Method method;
				Object resultObj;
				// 5.通过方法名获取方法
				method = clazz.getMethod(methodName);
				// 6.get方法没有参数,直接属性对应的值
				resultObj = method.invoke(this);
				if (resultObj != null && !"".equals(resultObj)) {
					result.append("[").append(fieldName).append("]").append(resultObj).append(" ");
				}
			}
		} catch (SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException
				| InvocationTargetException e) {
			e.printStackTrace();
		}
		return result.toString();
	}
}
public class ReflectTest {
	
	public static void main(String[] args){
	    Person person = new Person("xl","28");
	    System.out.println(person.toString());

	}
}

运行结果是:

[name]xl [age]28 

参考:

java核心技术之reflect(一):一个系统学习reflect的Demo(精)

JAVA深入研究——Method的Invoke方法

展开阅读全文

没有更多推荐了,返回首页