欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-30 20:48:14
...

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的方法,如果每有一个新类我们就写一个新的强制转换,这样的程序代码重复率太高了。