Java SE | 高级特性 | 反射
程序员文章站
2022-06-09 20:47:06
...
反射
反射是框架设计的灵魂~
-
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
-
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。
-
以上的总结就是什么是反射 :反射就是把java类中的各种成分映射成一个个的Java对象。
好处
- 运行过程中操作各种类的对象。
- 可以解耦,提高可拓展性。
示例
- 创建一个学生类
public class Student {
int id;
public String name;
public int age;
public boolean isTrue;
public Student(int id, String name, int age, boolean isTrue) {
this.id = id;
this.name = name;
this.age = age;
this.isTrue = isTrue;
}
public Student() {
System.out.println("Student正在完成初始化...");
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isTrue() {
return isTrue;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setTrue(boolean aTrue) {
isTrue = aTrue;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", isTrue=" + isTrue +
'}';
}
}
- 通过反射获取class对象的三种方式
public static void main(String[] args) throws Exception{
Student stu = new Student();
// 1.通过对象获取
Class<? extends Student> cls1 = stu.getClass();
// 2.通过类名获取
Class<Student> cls2 = Student.class;
// 3.通过字符串传参,此中方法可以从配置文件中获取,使用较多
Class<?> cls3 = Class.forName("demo1.Student");
}
- 获取构造方法
public static void main(String[] args) throws Exception{
// 获取Class对象
Class<?> cls = Class.forName("demo1.Student");
// 获取构造方法
Constructor<?>[] cons = cls.getConstructors();
for (Constructor<?> c: cons) {
System.out.println("名称"+":"+c.getName());
System.out.println("属性长度"+":"+c.getParameters().length);
}
// 获取有参构造
Constructor<?> dc1 = cls.getDeclaredConstructor(int.class,String.class,int.class,boolean.class);
// 获取无参构造
Constructor<?> dc2 = cls.getDeclaredConstructor();
// 使用构造
Object o1 = dc1.newInstance(1, "张三", 16, true);
System.out.println(o1);
Object o2 = dc2.newInstance();
System.out.println(o2);
}
- 获取属性
public static void main(String[] args) throws Exception {
// 创建Class对象
Class<?> cls = Class.forName("demo1.Student");
// 获取共有属性
Field[] fields = cls.getFields();
for (Field f : fields) {
System.out.println("属性名:"+f.getName());
System.out.println("类型:"+ f.getType());
System.out.println("=========================");
}
Field[] dfs = cls.getDeclaredFields();
for (Field c : dfs) {
System.out.println("属性名:"+c.getName());
System.out.println("类型:"+c.getType());
System.out.println("=========================");
}
// 单个属性获取
Field age = cls.getDeclaredField("age");
System.out.println(age.getType());
Object o = cls.getDeclaredConstructor().newInstance();
age.set(o,25);
System.out.println(o+"\n");
// 批量属性获取
Field[] declaredFields = cls.getDeclaredFields();
Object o2 = cls.getDeclaredConstructor().newInstance();
for (Field f : declaredFields) {
switch (f.getType().getName()) {
case "int":
System.out.println(f.getName());
f.set(o2,18);
break;
case "boolean":
System.out.println(f.getName());
f.set(o2,true);
break;
case "String":
System.out.println(f.getName());
f.set(o2,"张三");
break;
}
}
System.out.println(o2);
}
通过反射运行配置文件的内容
- 配置文件
className = demo2.Student
methodName = show
-
show()
方法
public class Student {
public static void show() {
System.out.println("is show()");
}
}
- 测试代码
public class Demo {
public static void main(String[] args) throws Exception {
Class<?> className = Class.forName(getValue("className"));
Method methodName = className.getMethod(getValue("methodName"));
methodName.invoke(className.getConstructor().newInstance());
}
public static String getValue(String key) throws IOException {
Properties prop = new Properties();
FileReader fr = new FileReader("./prop/stu.properties");
prop.load(fr);
fr.close();
return prop.getProperty(key);
}
}