Java学习自我总结——反射基础

Java反射基础

反射的意义:在不了解类结构,或者没有实例对象,或者类无法实例化的情况下动态的调用类方法(非静态方法)。

首先,准备一个Student类,

package chap07.sec2;

public class Student {
	private int id;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}}

类chap09.sec2.ReflectionTest2,

通过Class.forName获得类对象,通过强制转换成chap07.sec2.Student中Student对象,因为两个类在不同的package中,在强制转换的过程中自动导包。在取得对象的情况下调用setId(intid)&getId()两个方法,调用这两个方法的前提是:1.导包,并进行了强制转换;2.明确了解Student类的成员函数(实际上就是不满足“不了解类结构”这个条件,因为你其实已经明确的知道,Student类中存在这两个方法以及他们各自的方法参数);

public class ReflectionTest2 {
	public static void main(String[] args) {
		try {
			Class<?> clazz = Class.forName("chap07.sec2.Student");
			Student student = (Student) clazz.newInstance();
			student.setId(5);
			student.getId();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

类chap09.sec2.ReflectionTest,

仍然通过Class.forName获得类对象,注意:类对象的newInstance()方法生成的是一个Object的对象!因为不了解类结构,甚至不知道类的名字等等信息,通过getMethods()方法获得Method的对象method,method的getParameterTypes()方法获得该方法的参数类型(因为是测试,下图没有体现出来使用了method的getParameterTypes()方法),这时候使用invoke()来调用类的方法。

public class ReflectionTest {
	public static void main(String[] args) {
		try {
			Class<?> clazz = Class.forName("chap07.sec2.Student");
			Object object = clazz.newInstance();
			Method[] methods = clazz.getMethods();
			Method method1 = null;
			Method method2 = null;
			for (Method method : methods) {
				if (method.getName().equals("setId")) {
					method1 = method;
				}
				if (method.getName().equals("getId")) {
					method2 = method;
				}
			}
                        //省略了getParameterTypes()的过程
			method1.invoke(object, 5);
			System.out.println(method2.invoke(object, new Object[0]));
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Q&A

Q:我已经获得了实例对象,为什么不能用 . 直接调用方法,还需要invoke?

A:首先,1.我们可能并不了解类,没有办法做强制转换,而object显然是没有办法调用具体类的具体方法的;2.反射的目的是为了增加程序的通用性,我们可能对Student,Teacher,Manager等等一系列得类做类似上面代码中set和get的方法,如果每有一个新类我们就写一个新的强制转换,这样的程序代码重复率太高了。






猜你喜欢

转载自blog.csdn.net/qq_25445557/article/details/80063032