mzy对于反射的复习

    反射其实就是指在超脱规则的束缚从强引用到弱相关在上帝视角做事情,对于写配置文件,和一些框架的源码,得到调用上至关重要,java带有解释器的语法特性,使得泛型一类的语法糖和反射配合之后更如鱼得水!

    反射其实就是通过获得一个类的Class对象来进行操作,从而得到Constructor(构造方法:包括非共有;private、无类型、protected)对象、Method(方法:包括非共有;private、无类型、protected)对象和Field(变量,这个解释我也觉得不够准确:包括非共有;private、无类型、protected)对象来进行我们能够想象的所有操作!

 

Class类

得到类名称,类的实现的接口,继承类。

 

获得Class对象的三种方式:

1.类名.class;(依赖性较强,需要其中的import的支持)

Class c1 = Student.class;

2.Class.forName("全类名");(通过forName来加载,依赖性比较低)

Class c2 = Class.forName("c_flect.entity.Student");

3.对象.getClass();(一种单纯使用大多数时候,比较鸡肋的方法:通过对象来获得Class对类对象)

Class c3 = new Student().getClass();

常用方法:

 

getName() 获得全类名
getSimpleName() 仅获得当前类名
getSuperclass() 获得父类的名称(全类名)

getInterfaces()

返回值是Class[]数组,所有实现接口

 

涉及Constructor的
getConstructor 获取特定公开构造方法
getConstructors 获取所有公开构造方法
getDeclaredConstructor 获取特定的声明构造(包括非公开)
getDeclaredConstructors 获取所有的声明构造(包括非公开)
涉及Method的
getMethod 获取特定公开方法
getMethods 获取所有公开方法
getDeclaredMethod 获取特定的声明方法(包括非公开)
getDeclaredMethods 获取所有的声明方法(包括非公开)
涉及到Field的
getField 获取特定公开变量
getFields 获取所有公开变量
getDeclaredField 获取特定的声明变量(包括非公开)
getDeclaredFields 获取所有的声明变量(包括非公开)

 

其中需要注意的点:

1.所有如果是私有的构造方法、方法和变量要先setAccessible(true);才能进行使用

2.在get constructor、method和feild的时候,所有其中的形参类型,都是类型的.class Class对象

3.constructor最后newInstance就行了,method执行时调用invoke,field执行时调用set

4.method执行和field执行都要在执行方法的第一个位置传参传入执行此方法的对象(此方法的提供对象)

 

 

开始贴代码,使用junit测试:

package c_flect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.Test;

import c_flect.entity.Student;

/**
 * 反射复习:
 * 	Class类,代表类。
 * 		得到类名称,类的实现的接口,继承类。
 * 	Constructor类,代表类的构造方法。
 * 		构造对象。
 * 	Method类,代表类的普通方法。
 * 		调用方法。
 * 	Field类,代表类的属性。
 * 		得到属性值,设置属性值。
 * @author mzy
 */
public class Demo01 {
	/**
	 * Class类:
	 * 		测试得到Class类对象的三种方式回忆!		
	 */
	// @Test
	public void test01() throws  Exception {
		// 1.依赖性较强,需要其中的import的支持
		Class c1 = Student.class;
		// 2.通过forName来加载,依赖性比较低
		Class c2 = Class.forName("c_flect.entity.Student");
		// 3.一种单纯使用大多数时候,比较鸡肋的方法:通过对象来获得Class对类对象
		Class c3 = new Student().getClass();
		
		// 得到类名
		System.out.println(c1 == c2);
		System.out.println(c2 == c3);
		
		System.out.println(c1.getName()); // 得到类的全名
		System.out.println(c2.getSimpleName()); // 得到简单名
		// 得到类的继承的结构:得到当前的Student的父类
		System.out.println(c1.getSuperclass().getSimpleName()); 
		
		// 得到类的接口
		Class[] interArray = c1.getInterfaces();
		for (Class c : interArray) {
			System.out.println(c.getSimpleName());
		}
	}
	
	/**
	 * Constructor类:
	 * 		构造对象 
	 */
	@Test
	public void test02() throws Exception {
		// 通过Class类得到Constructor类
		Class c = Class.forName("c_flect.entity.Student");
		/*
		 *  获取所有的构造方法
		 *  但是获取到了所有的构造之后并并不好用,获取想要的才是最好的
		 *  统计有多少个构造方法可能有用。
		 */
		/*
		Constructor[] constructors = c.getConstructors();
		for(Constructor con : constructors) {
			System.out.println(con);
		}
		*/
		
		/*
		 * 1.调用无参构造
		 */
		Constructor cons1 = c.getConstructor(null);
		// 通过Constructor构造对象
		Object o1 = cons1.newInstance(null);
		// System.out.println(o1.getClass().getSimpleName());
		System.out.println(o1);
		/*
		 * 2.调用有参构造:私有
		 */
		Constructor cons2 = c.getDeclaredConstructor(int.class, String.class);
		// 设置这个私有构造的访问权限为true
		cons2.setAccessible(true);
		Object o2 = cons2.newInstance(19, "mzy");
		// System.out.println(o2.getClass().getSimpleName());
		System.out.println(o2);
	}
	
	/**
	 * Method类:
	 * 		类的普通方法,调用
	 */
	@Test
	public void test03() throws Exception {
		// 1.通过Class类 对象得到Method类对象
		Class c = Class.forName("c_flect.entity.Student");
		// Object o = c.getConstructor(null).newInstance(null);
		/*
		 * 同上:只有无参构造才可以这样简化!
		 * 有参构造必须 先getConstructor
		 * 再newInstance这种形式,或者
		 * getConstructor(int.class, String.class).newInstance(20, "mzy");
		 */
		Object o = c.newInstance();
	
		Method setName = c.getMethod("setName", String.class); // 如果有多个参数,跟在后面就行了
		/*
		 *  2) 通过Method对象来调用方法
		 *  	Method对象调用方法
		 *  	需要把要调用此方法的对象传入
		 *  	后面跟上参数值
		 */
		setName.invoke(o, "mzy");
		System.out.println(o);
		
		Constructor cons = c.getDeclaredConstructor(int.class, String.class, int.class);
		cons.setAccessible(true);
		
		Object o2 = cons.newInstance(18, "zxr", 168);
		Method getHeight = c.getDeclaredMethod("getHeight", null);
		getHeight.setAccessible(true);
		Object res = getHeight.invoke(o2, null);
		System.out.println("height = "+res);
		System.out.println(o2);
	}
	
	/**
	 * Field类:
	 * 		得到属性值,设置属性值。
	 */
	@Test
	public void test04() throws Exception {
		// 1) 通过Class得到Field类对象
		Class c = Class.forName("c_flect.entity.Student");
		// Object o = c.getConstructor(null).newInstance(null);
		Object o = c.newInstance();
		// 共有属性很简单,这里就演示非共有属性访问!
		Field field = c.getDeclaredField("name");
		field.setAccessible(true);
		field.set(o, "mzy");
		System.out.println(o);
	}
}

 

 

其中调用的Student类:

package c_flect.entity;

public class Student implements Person, Child{
	private int age;
	private String name;
	private int height;
	
	
	public Student() {
	
	}
	
	private Student(int age, String name) {
		this.age = age;
		this.name = name;
	}

	
	private Student(int age, String name, int height) {
		this.age = age;
		this.name = name;
		this.height = height;
	}


	public int getAge() {
		return age;
	}


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


	public String getName() {
		return name;
	}


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


	private int getHeight() {
		return height;
	}


	public void setHeight(int height) {
		this.height = height;
	}


	@Override
	public String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}
	
}




 

posted @ 2018-05-22 20:24  五彩世界  阅读(110)  评论(0编辑  收藏  举报