接上篇:JDK5.0新特性 (一)

反射

  • 应用在一些通用性比较强的代码中。
  • 后面学到的框架,大多数都是使用反射来实现的。
  • 在框架开发中,都是基于配置文件开发的。
    在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某个方法执行。
    类中的所有内容:属性、无参构造方法、有参构造方法、普通方法。

反射的原理:
JDK5.0新特性 (二)反射

  1. 首先把文件保存到本地硬盘,生成.java文件
  2. 编译java文件,生成.class文件
  3. 使用jvm,把class文件通过类加载器加载到内存中
  4. 万事万物都是对象,class文件在内存中使用Class类表示
  5. 当使用反射的时候,首先需要获取到Class类,得到这个类之后,就可以得到class文件里面的所有内容,包含:属性 构造方法 普通方法。
    属性通过一个类 Filed
    构造方法通过一个类 Constructor
    普通方法通过一个类 Method

反射操作类里面的属性

我们先创建一个类,以便后面的实验使用。

public class Person {
	// 属性
	private String name;
	private String id;

	// 没有参数的构造方法
	public Person() {
	}

	// 有参数的构造方法
	public Person(String name, String id) {
		this.name = name;
		this.id = id;
	}

	// 普通方法
	public String getName() {
		return name;
	}

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

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
}

使用反射操作 无参数的构造方法

  1. 获取class类
    三种方式:
    Class clazz1 = Person.class;
    Class clazz2 = new Person().getClass();
    Class clazz3 = Class.forName("com.veeja.test09.Person");
    

问题: 比如,要对一个类进行实例化,可以new,如果不使用new,该怎么获取?

@Test
private void test1() throws Exception {
	// 得到class
	Class c3 = Class.forName("com.veeja.test09.Person");
	// 得到Person类的实例
	Person p = (Person) c3.newInstance();
}
  1. 操作无参数的构造方法
    代码:
    @Test
    public static void test1() throws Exception {
    	// 得到class
    	Class c3 = Class.forName("com.veeja.test09.Person");
    	// 得到Person类的实例
    	Person p = (Person) c3.newInstance();
    	// 设置值
    	p.setName("zhangsan");
    	// 获取值
    	String name = p.getName();
    	System.out.println(name);
    }
    

使用反射操作 有参数的构造方法

  1. 得到类;
  2. 得到构造方法;
  3. 通过构造方法设置值并创建实例
@Test
// 操作有参数的构造方法
public static void test2() throws Exception {
	// 得到class
	Class c1 = Class.forName("com.veeja.test09.Person");

	// 使用有参数的构造方法

	// c1.getConstructors();//获取所有的构造方法

	// 传递的是有参数的构造方法里面的参数类型,类型使用class形式传递
	Constructor cs = c1.getConstructor(String.class, String.class);
	// 通过有参数的构造方法设置值
	// 通过有参数的构造方法创建Person实例
	Person p1 = (Person) cs.newInstance("lisi", "100");

	System.out.println(p1.getId() + " " + p1.getName());
}

使用反射操作 类的属性

  1. 得到类。
  2. 得到属性。
  3. 设置属性。
@Test
public static void test3() {
	try {
		// 得到class
		Class class1 = Class.forName("com.veeja.test09.Person");
		// 得到Person类的实例
		Person p = (Person) class1.newInstance();

		// 得到name属性
		// class1.getDeclaredFields();//得到所有的属性,用的很少
		Field f = class1.getDeclaredField("name");

		// 设置可以操作私有的属性
		f.setAccessible(true);

		// 设置name值
		f.set(p, "zhangsan");// 相当于p.name="zhangsan";
		System.out.println(f.get(p));// 相当于p.name
	} catch (Exception e) {
		e.printStackTrace();
	}
}

使用反射操作 类的普通方法

  1. 得到类
  2. 得到普通方法,使用getDeclaredMethod()方法,传递两个参数,第一个参数是方法的名称,第二个参数是通过方法设置的值的类型。
  3. 让方法来运行,使用invoke()方法,传递两个参数,一个是类的实例,另一个是设置的值。执行了invoke()方法之后相当于执行了serName()方法,并且通过这个方法设置了一个值。
  4. 如果操作的是私有的方法,也需要设置可以执行的权限:method.setAccessible(true);
  5. 静态方法调用的方式是类名.方法名(),不需要类的实例,所以使用反射操作静态方法的时候,也是不需要类的实例的:method.invoke(null, "zhangsan");
@Test
public static void test4() throws Exception {
	// 操作setName()方法

	// 得到class
	Class c = Class.forName("com.veeja.test09.Person");
	// 得到Person类的实例
	Person p = (Person) c.newInstance();
	// 得到普通的方法

	// c.getDeclaredMethods();//得到所有的普通方法,用的很少
	Method m = c.getDeclaredMethod("setName", String.class);

	//如果操作的是私有的方法,也需要设置可以执行的权限
	m.setAccessible(true);
	
	// 让setName方法执行,执行设置值
	m.invoke(p, "zhangsan");
	System.out.println(p.getName());
}

end.

相关文章: