反射: 将类的各个组成部分封装成其它对象,如成员变量封装成Field,构造方法封装成Constructor,成员方法封装成Method
反射好处:
- 可以在运行阶段操作这些对象
- 可以代码解耦,提高程序的可扩展性
获取Class类对象的三种方式:
- Class.forName(“类的全类名”)
- 类名.class
- 对象.getClass()
Person类
package codewen.reflect;
/**
* @author codewen
*/
public class Person {
public String a1;
public String a2;
protected int b;
int c;
private int d;
public Person() {
}
public Person(String a1, String a2) {
this.a1 = a1;
this.a2 = a2;
}
@Override
public String toString() {
return "Person{" +
"a1='" + a1 + '\'' +
", a2='" + a2 + '\'' +
", b=" + b +
", c=" + c +
", d=" + d +
'}';
}
public void eat() {
System.out.println("吃....");
}
public void eat(String s1, String s2) {
System.out.println("吃"+s1+"和"+s2);
}
}
GetClass类
package codewen.reflect;
/**
*
* @author codewen
*/
public class GetClass {
public static void main(String[] args) throws Exception {
//1.Class.forName("类的全类名")
Class cls1 = Class.forName("codewen.reflect.Person");
System.out.println(cls1);
//2.类名.class
Class cls2 = Person.class;
System.out.println(cls2);
//3.对象.getClass()
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
//============================
System.out.println("============================");
System.out.println(cls1==cls2); //true
System.out.println(cls1==cls3); //true
System.out.println(cls2==cls3); //true
}
}
结论: 通过比较三种不同方式获得的Class对象,可以发现他们获取的对象都是同一个,所以,相同字节码文件的Class对象只有一个!
获取Field对象:
package codewen.reflect;
import java.lang.reflect.Field;
/**
* 获取Field对象
* @author codewen
*/
public class GetFields {
public static void main(String[] args) throws Exception {
//获取Class对象
Class personClass = Person.class;
//getField(String name):获取指定名字的Field对象(只能是公共的)
System.out.println("===========getField================");
Field f1 = personClass.getField("a1");
System.out.println(f1);
//getFields():获取所有的Field对象(只能是公共的)
System.out.println("===========getFields================");
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
//getDeclaredField(String name):获取指定名字的Filed对象(可以是任意权限的)
System.out.println("===========getDeclaredField================");
Field f2 = personClass.getDeclaredField("b");
Field f3 = personClass.getDeclaredField("d");
System.out.println(f2);
System.out.println(f3);
//getDeclaredFields():获取所有的Filed对象(可以是任意权限的)
System.out.println("===========getDeclaredFields================");
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//操作属性
//getDeclaredField获取的Field对象操作属性只能操作除private修饰的
//要想操作private修饰的,需要用暴力反射setAccessible(true)来忽略权限修饰符的安全检查
System.out.println("=========操作属性================");
Person p = new Person();
Field c = personClass.getDeclaredField("c");
c.set(p, 1);
System.out.println(c.get(p));
Field d = personClass.getDeclaredField("d");
//暴力反射 用来忽略权限修饰符的安全检查
d.setAccessible(true);
d.set(p, 2);
System.out.println(d.get(p));
}
}
获取Constructor对象:
package codewen.reflect;
import java.lang.reflect.Constructor;
/**
* 获取Constructor对象
* @author codewen
*/
public class GetConstructors {
public static void main(String[] args) throws Exception {
//获取Class对象
Class personClass = Person.class;
//getConstructor(类<?>... parameterTypes):获取指定名字的Constructor对象(只能是公共的)
//参数是不定长参数类型(构造器的参数类型,可以有也可以没有)
System.out.println("===========getConstructor================");
Constructor con1 = personClass.getConstructor(); //无参构造
Constructor con2 = personClass.getConstructor(String.class, String.class); //有参构造
System.out.println(con1);
System.out.println(con2);
//getConstructors():获取所有的Constructor对象(只能是公共的)
System.out.println("===========getConstructors================");
Constructor[] constructors = personClass.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//getDeclaredConstructor(类<?>... parameterTypes):获取指定名字的Constructor对象(可以是任意权限的)
//要想操作private修饰的,需要用暴力反射来忽略权限修饰符的安全检查
//使用与上面类似,不同之处为权限不同
System.out.println("===========getDeclaredConstructor================");
//getDeclaredConstructors():获取所有的Constructor对象(可以是任意权限的)
//要想操作private修饰的,需要用暴力反射来忽略权限修饰符的安全检查
//使用与上面类似,不同之处为权限不同
System.out.println("===========getDeclaredConstructors================");
//创建对象
System.out.println("============Constructor对象创建对象=================");
//对于无参
Object o1 = con1.newInstance();
System.out.println(o1);
//对于有参(参数是构造方法所需的参数)
Object o2 = con2.newInstance("张三", "李四");
System.out.println(o2);
//无参形式可以简化
Object o3 = personClass.newInstance();
System.out.println(o3);
}
}
获取Method对象:
package codewen.reflect;
import java.lang.reflect.Method;
/**
* 获取Method对象
* @author codewen
*/
public class GetMethods {
public static void main(String[] args) throws Exception {
//获取Class对象
Class personClass = Person.class;
//getMethod(String name, 类<?>... parameterTypes):获取指定名字的Method对象(只能是公共的)
System.out.println("===========getMethod================");
//getMethods():获取所有的Method对象(只能是公共的)
System.out.println("===========getMethods================");
//getDeclaredMethod(String name, 类<?>... parameterTypes):获取指定名字的Method对象(可以是任意权限的)
//第一个参数是方法名,第二个参数是不定长参数类型(方法所需要的参数类型)
System.out.println("===========getDeclaredMethod================");
Person p = new Person();
//调用方法invoke(Object obj, Object... args)
//第一个参数是对象,第二个参数是方法所需的参数
//获取无参的Method对象
Method m1 = personClass.getDeclaredMethod("eat");
//调用无参的方法
Object invoke1 = m1.invoke(p);
//获取有参的Method对象
Method m2 = personClass.getDeclaredMethod("eat", String.class, String.class);
Object invoke2 = m2.invoke(p, "饭", "菜");
//getDeclaredMethods():获取所有的Method对象(可以是任意权限的)
System.out.println("===========getDeclaredMethods================");
}
}