Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性,Java反射就是通过Class文件对象去使用自身类的成员变量 、构造方法、成员方法等属性。
我们无法new出一个Class对象,因为其构造函数为private,这个Class类的对象是在当各类被调入时,由 Java 虚拟机自动创建 Class 对象。
程序中一般的对象的类型都是在编译期就确定下来的,而反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,Java反射机制可以动态地创建对象并调用其属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
下面来记录下反射的常用操作,先码个人对象类:
public class Person {
private String name;
private int age;
public String address;
public Person() {
super();
}
private Person(String name) {
this.name=name;
}
public Person(String name, int age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
}
public void show() {
System.out.println("show()");
}
public String show(String s) {
System.out.println("show("+s+")");
return s;
}
}
获取Class对象的方式:
1.Object类的getClass()方法:
Person p=new Person();
Class c=p.getClass();
2.数据类型的静态属性:
Class c=Person.class;
3.Class类的静态方法:
Class c=Class.forName("cn.itcast.fanshe.Person");
值得注意的是,第二种办法生成Class类对象时,不会使JVM自动加载该Person类。而其他办法会使得JVM初始化该类。
通过构造方法创建对象实例:
Constructor con=c.getConstructor();//获取无参构造方法对象
Object obj=con.newInstance();//创建对象
Constructor con=c.getConstructor(String.class,int.class,String.class);//获取带参构造方法对象
Object obj=con.newInstance("wanna",24,"China");
Constructor con=c.getDeclaredConstructor(String.class);//获取私有构造方法对象
con.setAccessible(true);//这里要记得设置私有可访问
Object o=con.newInstance("kobe");
Object o=c.newInstance();//还可以直接通过Class文件对象创建对象
反射获取成员变量并使用:
Field addressField=c.getField("address");//获取address成员变量
Object obj=c.newInstance();
addressField.set(obj, "北京");//给address赋值,通过obj隐藏了Person对象
Field nameField=c.getDeclaredField("name");//获取私有成员变量
nameField.setAccessible(true);//也要记得设置私有可访问
nameField.set(obj, "kobe");
反射获取成员方法并使用:
Method m1=c.getMethod("show");//这里传方法名
m1.invoke(obj);
Method m2=c.getMethod("show", String.class);//调用带参方法要传入参数类型的.class文件
m2.invoke(obj, "hello");