反射就是从内存当中找类的相关信息,从而构建一个对象,然后可以执行一系列的操作
简单说一下,类的字节码文件被加载到内存之后,就会构建一个Class对象,来保存相关类的信息与接口,我们反射的目的就是拿到这个Class对象进行操作。
既然是对象,那么内部就会有很多功能,有什么功能推也能推测出来,对象嘛,就有什么涉及成员变量的,成员方法的,还有构造方法的一系列操作
下面还需要来说明一下,这个传入的是啥:
可变函数参数,是一个Class类型,所以,参数也是传入该参数在内存中的class对象,别忘了,数据类型就是一个对象。
代码实例:
首先看一下我们放在domain下面的一个类:
package domain; public class Person { private String name; private int age; public String a; protected String b; String c; private String d; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat(){ System.out.println("eat..."); } public void eat(String food){ System.out.println("eat..."+food); } }
然后利用反射来构造一个对象:
package reflect; import domain.Person; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Reflect2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获得class类对象,类文件 Class person = Class.forName("domain.Person"); //根据反射创建一个对象 Constructor[] cons = person.getConstructors(); for(Constructor data : cons) { System.out.println(data); } System.out.println("-----------"); //利用反射构造一个对象 Constructor cons1 = person.getConstructor(String.class,int.class); Object obj = cons1.newInstance("王五",20); Person p1 = (Person)obj; System.out.println(p1.getName()); } }
利用反射来执行某个对象的方法:
package reflect; import domain.Person; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Reflect3 { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { //得到Class类对象 Class obj = Person.class;//得到对象 Method[] method = obj.getDeclaredMethods(); for(Method data : method) { System.out.println(data); data.setAccessible(true); } System.out.println("-------"); //得到具体某一个方法,然后执行 Method method_eat = obj.getMethod("eat");//没有参数 Person p = new Person(); // method_eat.setAccessible(true);暴力破解对方法无效 method_eat.invoke(p); } }
在来看一个实例:
根据配置文件来找构建一个对象,然后执行一个方法:
什么是配置文件:以.properties结尾的文件,我们需要把这个配置文件以文件流的形式加载到内存中,传给Properties对象来获取相关信息。
上面包含了加载的对象与需要执行的方法,下面看整体代码:
package reflect; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Properties; public class ReflectTest { public static void main(String[] args) throws IOException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException { //加载Properties对象 Properties pro = new Properties(); //获得一个类加载器,去寻找配置文件,你都能找到类文件还找不到配置文件 ClassLoader classLoader = ReflectTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("pro.properties"); //加载配置文件 pro.load(is); //在配置文件中定义数据 String className= pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //加载该类进内存,找到这个类的字节码对象 Class cls = Class.forName(className); Constructor cons = cls.getConstructor(); //获得一个obj对象 Object obj = cons.newInstance(); //获取方法对象 Method method = cls.getMethod(methodName); //再来执行方法 method.invoke(obj); } }