一,反射的概念
在运行状态中,这通过Reflection APIs取得任何一个已知名称的class的内部信息以及任意一个对象的内部信息,并且可以调用它的任意一个方法和属性;
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
二,Class类
(一)获取class对象
- 获取Class对象的方式:
- Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
- 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
- 类名.class:通过类名的属性class获取
- 多用于参数的传递
- 对象.getClass():getClass()方法在Object类中定义着。
- 多用于对象的获取字节码的方式
- 多用于对象的获取字节码的方式
- Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
运行时程序,jvm先把Person.java中的Person编译为Person.class文件 ,在通过jvm中的类加载器加载Person.class到jvm内存中,然后使用对象的反射机制映射类加载器中的类对象,达到获取对象
Person person= new Person()
Class cls1 = person.getClass();
调试
public class DemoReflection {
public static void main(String[] args) throws ClassNotFoundException{
Class cls1 = Class.forName("domain.Person");
System.out.println(cls1);
Class cls2 = Person.class;
System.out.println(cls2);
Class cls3 = danew Person().getClass();
System.out.println(cls3);
System.out.println(cls1 == cls2);
System.out.println(cls1 == cls3);
}
}
运行结果:
class domain.Person
class domain.Person
class domain.Person
true
true
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
(二)反射构造函数
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("有参构造函数被调用 "+this.name);
}
}
try{
Constructor constructor1 = personClass.getConstructor(String.class, int.class);
System.out.println(constructor1);
Constructor constructor2 = personClass.getConstructor();
System.out.println(constructor2);
//调用构造方法
Object obj = constructor1.newInstance("bai",20);
System.out.println("*******************");
}catch (NoSuchMethodException | InstantiationException | InvocationTargetException e){
e.printStackTrace();
}
进调试看看
(三)反射成员变量
Person类
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person() {
a = "a";
}
}
public static void main(String[] args) {
Class personClass = Person.class;
Field[] fields = personClass.getFields();//返回一个 Field 对象数组
for (Field field : fields) {
System.out.println(field);
}
Field a = personClass.getField("a"); // 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Person person = new Person();
System.out.println(a.get(person));
a.set(person,"new_a"); // 将指定对象参数上由此字段对象表示的字段设置为指定的新值
System.out.println( a.get(person));
}
(四)反射成员方法
Class personClass = Person.class;
try{
//获取指定名称的方法
Method eat_method = personClass.getMethod("getName");
Person person = new Person("bai",20);
//执行方法
Object value = eat_method.invoke(person); //执行成员方法,如果有返回值则返回
System.out.println(value);
}catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e){
e.printStackTrace();
}
(五)反射main
public class Person {
public static void main(String[] args) {
System.out.println("这是person的mai方法");
}
}
try {
// 获取main方法
Method methodMain = personClass.getMethod("main", String[].class);//第一个参数:方法名称,第二个参数:方法形参的类型,
//需要将new String[]{} 拆成3个对象。。。所以需要将它强转
methodMain.invoke(null, (Object)new String[]{"a","b","c"});
} catch (Exception e) {
e.printStackTrace();
}
结语,反射是java进阶中,非常重要的内容,如果哪里写得不对,请在下方评论