类对象和类的对象不同。对于某类xxx,类的对象就是xxx类实例化之后的对象。而类对象就是用来描述这个类拥有什么属性和什么方法。
在获取类对象的时候,会导致类属性被初始化。也就是说静态属性,静态代码块都会在类对象被获取时直接被初始化。
package reflection;
public class TestReflection3 {
public static void main(String[] args){
String className = "character.Staff";
try{
Class t1 = Class.forName(className);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
}
package character;
public class Staff {
static String company;
static{
company = "BAC";
System.out.println(company+"版权所有");
}
private int id;
private String name;
private String department;
}
输出结果为BAC版权所有
1. 获取类对象有三种方式:
1. Class.forName
2. xxx.class
3. new xxx().getClass()
获取的类对象只有一个。这三种获取方式中,只有Class t2 = Staff.class这种方式不会导致静态属性被初始化。
2. 通过反射创建对象
传统方法构建新对象,需要通过new关键字来实例化对象。而反射机制,先会获取xxx类的类对象,再通过类对象获取构造器对象,最后通过构造器对象创建实例对象。
package reflection;
import java.lang.reflect.Constructor;
import character.Staff;
public class TestReflection3 {
public static void main(String[] args){
Staff s1 = new Staff();
s1.id = 1;
s1.name = "Jack";
s1.department = "technique";
System.out.println(s1);
try{
String className = "character.Staff";
Class t = Class.forName(className);
Constructor c = t.getConstructor();
Staff s2 = (Staff) c.newInstance();
s2.name = "Tom";
s2.id = 2;
s2.department = "technique";
System.out.println(s2);
}catch(Exception e){
e.printStackTrace();
}
}
}
其中Java文档中对于getConstructor(Class<T>...parameterTypes)和newInstance(Object... initargs)的解释
getConstructor(Class<?>... parameterTypes)
Returns a Constructor
object that reflects the specified public constructor of the class represented by this Class
object.
使用时,传入参数格式为(Staff.class)
newInstance(Object... initargs)
Uses the constructor represented by this Constructor
object to create and initialize a new instance of the constructor's declaring class, with the specified initialization parameters.
使用时,根据Staff类的有参构造方法的参数列表public Staff(String a),传入参数格式为("test")。
3. 通过反射机制改变属性值/通过反射机制调用方法
getField 和 getDeclaredField的区别:
getField()只能获取public的属性,可以获取某类从父类继承来的属性。
getDeclaredField()可以获取本类中所有已经声明的属性,包括private protected default。但不能获取该类从父类继承来的字段。
注意可以通过反射机制在类对象中用getDeclaredMethod()获取某个private的属性,但获取private属性之后不能修改它的值。
那么getMethod()和getDeclaredMethod()的区别同上。
对于Method.invoke()
参数分别为
obj the object the underlying method is invoked from 调用的方法所来源的类的实例
args the arguments used for the method call 即将传入的参数
返回
the result of dispatching the method represented by this object on obj
with parameters args
例子编写:
package character;
public class Staff2 {
private int id;
private String name;
private String department;
public String company;
public void setId(int id){
this.id = id;
}
public int getId(){
return id;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setDepartment(String department){
this.department = department;
}
public String getDepartment(){
return department;
}
public String toString(){
return "员工信息: "+id+" "+name+" "+department+" "+company;
}
}
package reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import character.Staff2;
public class TestReflection4 {
public static void main(String[] args){
//以new方式获取Staff2对象
Staff2 a = new Staff2();
a.setName("Jack");
a.setId(1);
a.setDepartment("marketing");
System.out.println(a);
//以反射方式修改属性值
try{
Method m1 = Class.forName("character.Staff2").getMethod("setId",int.class);
Method m2 = a.getClass().getMethod("setName",String.class);
Method m3 = Staff2.class.getMethod("setDepartment",String.class);
//Field f1 = a.getClass().getDeclaredField("department");
Field f2 = a.getClass().getField("company");
m1.invoke(a, 2);
m2.invoke(a, "Terry");
m3.invoke(a, "technique");
//f1.set(a,"BAC");
f2.set(a,"BAC");
System.out.println(a);
}catch(Exception e){
e.printStackTrace();
}
}
}