Java第三十七天,基础增强,反射
框架设计的灵魂——反射
1.概述
将类的各个组成部分封装为其他对象,这就是反射机制
反射机制的优点
①在程序运行过程中,操作这些对象
②可以解耦,提高程序的可扩展性
2.反射机制流程图
3.如何获取Class对象
因为反射是将类的各个组成部分封装为其他对象,那么我们根据流程图可知获取类的关键一步就是获取指定类的字节码文件(.class文件)。获取类对象一般有以下三个方法
- Class.forName(完整路径) ===> 将字节码文件加载进内存,返回Class对象(对应于Source源代码阶段)
- [类名].class ===> 通过类的属性class获取(对应于Class类对象阶段)
- [对象].getClass() ===> 通过对象的getClass() 方法获取(对应于Runtime运行时阶段)
同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
4.操作Class对象
注意:
①除了代码中举的例子外,Class还有很多方法,可以自行参考API文档
②在反射面前,属性和方法没有共有私有之分。即无论是public还是private还是其他,都可以获取并设置
见如下代码:
Dog实体类
package 反射;
public class Dog {
public int age;
public String name;
private String sex;
public Dog(){
age = 3;
name = "二哈";
sex = "雌";
}
public Dog(int age, String name){
this.age = age;
this.name = name;
}
public void eat(){
System.out.println(age + "岁的" + name + "正在吃饭");
}
public String getSex(){
return sex;
}
@Override
public String toString() {
return "Dog{" +
"age=" + age +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
(1)获取并设置属性
package 反射;
import sun.font.TrueTypeFont;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.security.cert.TrustAnchor;
public class Realize {
public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException {
Class dogClass = Dog.class;
//getFields()方法只获取被public修饰的属性
Dog myDog = new Dog();
Field[] fields = dogClass.getFields();
for (Field attr : fields){
//输出类的所有public属性
System.out.println(attr);
//输出myDog对象中的所有属性值
System.out.println(attr.get(myDog));
}
//得到类Dog的name属性
Field field = dogClass.getField("name");
System.out.println(field.get(myDog));
//将myDog对象的name属性设置为萨摩耶
field.set(myDog, "萨摩耶");
System.out.println(field.get(myDog));
Field[] dFields = dogClass.getDeclaredFields();
for (Field dField : dFields) {
//忽略因访问非public属性方法而引发的安全检查 ---> 暴力反射
dField.setAccessible(true);
System.out.println(dField.get(myDog));
}
//得到类Dog的私有属性sex
Field dField = dogClass.getDeclaredField("sex");
//忽略因访问非public属性方法而引发的安全检查 ---> 暴力反射
dField.setAccessible(true);
//设置myDog对象的性别为雄性
dField.set(myDog, "雄");
System.out.println(myDog.getSex());
}
}
(2)获取并使用构造方法
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class RealizeCon {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class dogClass = Dog.class;
//得到所有的构造方法
Constructor[] cons = dogClass.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
//得到指定的构造方法,根据参数确定
Constructor con = dogClass.getConstructor(int.class, String.class);
System.out.println(con);
Dog myDog = (Dog) con.newInstance(5, "德牧");
myDog.eat();
Object myDogTwo = con.newInstance(4, "土狗");
System.out.println(myDogTwo);
}
}
(3)获取并使用成员方法
package 反射;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class RealizeMethod {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class dogClass = Dog.class;
Dog myDog = new Dog();
//getDeclaredMethods()方法为查询所有方法,包括私有、保护等等
Method[] methods = dogClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//如果有重载,除了传方法名之外,还需要传参数列表
Method method = dogClass.getMethod("eat");
//如果方法有参数,后面传入参数即可
method.invoke(myDog);
}
}