反射就是从内存当中找类的相关信息,从而构建一个对象,然后可以执行一系列的操作
简单说一下,类的字节码文件被加载到内存之后,就会构建一个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);
}
}