Java反射解析

一 反射简述

     JAVA是一个静态语言,但是通过使用反射,我们可以在程序运行的时候获取一个类的所有的方法,属性,并且实现调用。

二 反射的使用

1.我们首先创建一个学生类

package markorg.top.demo;

public class Student {

	private int age;
	public String name;
	private String school;

	public Student() {
		System.out.println("默认的构造方法");

	}

	// 受保护的构造方法
	protected Student(int age) {
		System.out.println("受保护的构造方法" + age);
	}

	// 私有构造方法
	private Student(int age, String name) {
		System.out.println("受保护的构造方法" + "age: " + age + ",name: " + name);
	}

	// 完整的构造方法
	public Student(int age, String name, String school) {
		super();
		this.age = age;
		this.name = name;
		this.school = school;
	}

	public void print(String str) {
		System.out.println("hello student:" + str);
	}

	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;
	}

	public String getSchool() {
		return school;
	}

	public void setSchool(String school) {
		this.school = school;
	}

}
 
 
2.接下来,首先通过反射获取Student 类的Class,然后调用reflect api获取到类的构造方法,实现类的初始化
package markorg.top.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflectTest {

	public static void main(String[] args) throws InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		Student stu = new Student();

		// 第一种方式获取student对象
		Class stuClass = stu.getClass();// 这种方法是在已经创建的情况下获取,实际中不需要
		System.out.println(stuClass.getName());

		// 第二种方式获取student对象
		Class stuClass2 = Student.class;

		// 第三种方式获取student对象,常用的方法,需要注意的是Name需要包的完整路径名和类的名称
		try {
			Class stuClass3 = Class.forName("markorg.top.demo.Student");
			System.out.println(stuClass == stuClass2);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

		// 获取公有的构造方法
		Constructor[] conArry = stuClass2.getConstructors();
		System.out.println("公有构造");
		for (Constructor con : conArry) {
			System.out.println(con);
		}

		// 获取所有的构造方法
		Constructor[] conAll = stuClass2.getDeclaredConstructors();
		System.out.println("所有构造");
		for (Constructor cons : conAll) {
			System.out.println(cons);
		}

		Constructor ctr = stuClass2.getConstructor(null);
		// 调用构造
		Object obj = ctr.newInstance();

		// 带参数的构造方法
		Constructor ctr2 = stuClass2.getDeclaredConstructor(int.class);
		// 调用构造
		Object ob = ctr2.newInstance(20);

		Constructor pri = stuClass2.getDeclaredConstructor(int.class, String.class);// 注意,这里只能是类型.class,不能直接他的包装类型。
		// 调用构造

		// 设置可以访问
		pri.setAccessible(true);
		Object ob3 = pri.newInstance(18, "tom");

	}

}
 
 

3.获取类的属性,方法,并且调用方法

package markorg.top.demo;

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

public class GetFieldTest {
	public static void main(String[] args) {
		try {
			// 通过反射获取Class
			Class stuClass = Class.forName("markorg.top.demo.Student");

			// 获取所有公有字段
			Field[] field = stuClass.getFields();
			for (Field fd : field) {
				System.out.println("公有字段:" + fd);
			}

			// 获取所有的字段
			Field[] fields = stuClass.getDeclaredFields();
			for (Field fds : fields) {
				System.out.println("全部字段:" + fds);
			}

			// 获取私有字段并调用
			Field fie = stuClass.getDeclaredField("school");
			fie.setAccessible(true);
			Object obb = stuClass.getConstructor().newInstance();
			fie.set(obb, "苏州大学");

			Student stt = (Student) obb;
			System.out.println("学校名字:" + stt.getSchool());

			// 获取所有的方法
			Method[] method = stuClass.getMethods();
			for (Method met : method) {
				System.out.println("全部方法:" + met);
			}

			// 获取公有的某个方法,通过方法名来获取
			Method pubmethod = stuClass.getMethod("print", String.class);
			System.out.println("私有方法:" + pubmethod);
			// pubmethod.setAccessible(true);如果是私有方法需要这个
			pubmethod.invoke(obb, "jack");//通过invoke来进行调用

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("反射异常");

		}
	}

}



三 反射总结

    乍看起来,我们好像没必要使用反射,因为正常情况下,通过实例化类,就可以直接使用他的方法,而且,反射会降低程序的性能,但是,有时候,我们是不知道这个类的属性的,比如一些ORM框架中,需要数据库中的表来和类进行映射,但是我们一开始是不知道将要映射的表是什么样的,是不能提前创建对应的类,这时候我们可以可以通过查询数据库,动态的生成表对应的class并且通过java自编译器动态加载到内存,达到动态生成对象进行映射的作用。相关操作,我将在下一个章节进行介绍。


猜你喜欢

转载自blog.csdn.net/csgarten/article/details/80149703