了解反射先要了解字节码文件对象
Class类
字节码文件对象 就是 Class 类的对象
这个 Class 和 定义一个类的 class 关键字是不一样的, class 是用来定义一个类, Class 是 Java 中的一个类型;
字节码文件
java 源文件 进行编译(javac)之后的 .class文件。
字节码文件对象
jvm 将字节码文件加载到 jvm 内存中, jvm就 认为这个字节码文件是一个字节码文件对象;
如何获取字节码文件对象
1、Object 类的 getClass 方法;
Person p = new Person();
Class class1 = p.getClass();
2、类型 .class 属性
Class class2 = Person.class;
3、Class.forName("类的路径")
Class class3 = Class.forName("com.jm.pojo.Person");
使用字节码文件对象
1、字节码文件包含
类 字节码文件对象
构造方法 构造方法对象 (类型 Constructor )
成员变量 成员变量对象 (类型 Field )
成员方法 成员方法对象 (类型 Method )
2、用字节码文件对象构建一个类的对象
2.1、用 new 创建对象
之前用 new 的 方式创建一个类的对象
Person p = new Person();
Person() 是类的构造方法,因为对象是通过构造方法创建;
2.2、用字节码文件中的构造器对象来创建一个类的对象 ---- Constructor对象
Person
public class Person implements Serializable {
public Person(){};
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
private String name;
private Integer age;
public void eat(){
System.out.println("吃饭。。。");
}
}
测试
public static void main(String[] args) throws Exception{
Person p = new Person();
// 用字节码文件对象创建一个类的对象
Class clazz = Class.forName("com.jm.pojo.Person");
// 得到字节码文件中的构造器对象
Constructor[] constructors = clazz.getConstructors();
System.out.println(constructors.length);
System.out.println(constructors[0]);
System.out.println(constructors[1]);
Constructor c = constructors[0];
// 用构造器对象常见类的对象
Object obj = c.newInstance();
Person p2 = (Person) obj;
p2.eat();
}
打印
2
public com.jm.pojo.Person()
public com.jm.pojo.Person(java.lang.String,java.lang.Integer)
吃饭。。。
3、构造方法对象( Constuctor )
3.1、方法对象( Method )
getMethods() : 获取到包括父类继承过来的方法
getDeclaredMethods() : 获取类当前的所有方法
Person p = new Person();
// 用字节码文件对象创建一个类的对象
Class clazz = Class.forName("com.jm.pojo.Person");
// 得到字节码文件中的构造器对象
Method[] methods = clazz.getDeclaredMethods();
for(Method method: methods){
System.out.println(method);
}
打印
public java.lang.String com.jm.pojo.Person.getName()
public void com.jm.pojo.Person.setName(java.lang.String)
public java.lang.Integer com.jm.pojo.Person.getAge()
public void com.jm.pojo.Person.eat()
public void com.jm.pojo.Person.setAge(java.lang.Integer)
3.2、获取特定方法
getMethod("the name of the method")
3.2.1 执行特定方法 invoke
传统调用方法 : 对象 。方法 ( 实参 )
反射调用方法 : 方法 。invoke (对象, 实参)
如果方法是private 则 先获取 getDeclaredMethod 再 setAccessble(true)
给 Person 类加个方法
public String method(String param){
System.out.println("get method "+ param);
return param;
}
测试调用特定方法
public static void main(String[] args) throws Exception{
Person p = new Person();
// 用字节码文件对象创建一个类的对象
Class clazz = Class.forName("com.jm.pojo.Person");
// 得到字节码文件中的构造器对象
Method method = clazz.getMethod("method", String.class);
System.out.println(method);
// 字节码文件对象提供一个边界创建类对象的方法
Object newInstance = clazz.newInstance();
// 反射调用
Object rst = method.invoke(newInstance, "test");
System.out.println(rst);
}
打印
public java.lang.String com.jm.pojo.Person.method(java.lang.String)
get method test
test
4、成员变量
getFileld