当前位置: 首页 > news >正文

JavaSE——反射

目录

一、反射的概念

二、获取class对象的三种方式

三、使用反射获取构造方法

(一)Class类中用于获取构造方法的方法

1.获取所有公共构造方法

2.获取所有构造方法

3.获取单个公共构造方法对象

4.获取单个构造方法对象

(二)Constructor类中用于创建对象的方法

四、使用反射获取成员变量

(一)Class类中用于获取成员变量的方法

(二)Field类中用于创建对象的方法

五、使用反射获取成员方法

(一)Class类中用于获取成员方法的方法

(二)Method类中用于创建对象的方法

六、反射的作用

(一)使用反射保存任意对象数据

(二)反射结合配置文件,动态地创建对象并调用方法


一、反射的概念

        反射是Java的一种能力,它允许程序在运行时检查和操作自身的结构和行为。通过反射,可以获取类的信息(如字段、方法、构造函数等),并可以动态地调用方法、访问字段等。反射是通过java.lang.reflect包中的类和接口来实现的。

二、获取class对象的三种方式

  1. 在源代码阶段,即此时只有.java和.class文件:使用Class.forName("全类名")
  2. 在加载阶段,此时将.class文件加载到内存中:使用类名.class
  3. 在运行阶段,此时创建了类的实例对象:使用对象.getClass()

Student类:

@Data
public class Student {private String name;private int age;public Student() {}public Student(String name) {this.name = name;}protected Student(int age) {this.age = age;}private Student(String name, int age) {this.name = name;this.age = age;}
}
public class MyReflectDemo1 {public static void main(String[] args) throws ClassNotFoundException {// 方式一:最常用Class clazz1 = Class.forName("com.testdemo.Student");System.out.println(clazz1);// 方式二:经常当做参数来传递Class clazz2 = Student.class;// 方式三:有了这个类的对象时,才可以使用Student student = new Student();Class clazz3 = student.getClass();System.out.println(clazz1 == clazz2); // trueSystem.out.println(clazz1 == clazz3); // trueSystem.out.println(clazz2 == clazz3); // true}
}

三、使用反射获取构造方法

(一)Class类中用于获取构造方法的方法

方法名作用
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes)返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)返回单个构造方法对象

1.获取所有公共构造方法

Class clazz = Class.forName("com.testdemo.Student");
Constructor[] conn1 = clazz.getConstructors();
for (Constructor constructor : conn1) {System.out.println(constructor);
}
/*** public com.testdemo.Student(java.lang.String)* public com.testdemo.Student()*/

2.获取所有构造方法

Constructor[] conn2 = clazz.getDeclaredConstructors();
for (Constructor constructor : conn2) {System.out.println(constructor);
}
/*** private com.testdemo.Student(java.lang.String,int)* protected com.testdemo.Student(int)* public com.testdemo.Student(java.lang.String)* public com.testdemo.Student()

3.获取单个公共构造方法对象

Constructor conn3 = clazz.getConstructor();
System.out.println(conn3);
// public com.testdemo.Student()Constructor conn4 = clazz.getConstructor(String.class);
System.out.println(conn4);
// public com.testdemo.Student(java.lang.String)

4.获取单个构造方法对象

Constructor conn5 = clazz.getDeclaredConstructor();
System.out.println(conn5);
// public com.testdemo.Student()Constructor conn6 = clazz.getDeclaredConstructor(String.class);
System.out.println(conn6);
// public com.testdemo.Student(java.lang.String)System.out.println(conn6.getModifiers());
// public修饰的构造方法,返回1Constructor conn7 = clazz.getDeclaredConstructor(int.class);
System.out.println(conn7);
// protected com.testdemo.Student(int)System.out.println(conn7.getModifiers());
// protected修饰的构造方法,返回4Constructor conn8 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(conn8);
// private com.testdemo.Student(java.lang.String,int)System.out.println(conn8.getModifiers());
// private修饰的构造方法,返回2// 获取构造方法的每个参数
Parameter[] parameters = conn8.getParameters();
for (Parameter parameter : parameters) {System.out.println(parameter);
}
/*** java.lang.String arg0* int arg1* */

(二)Constructor类中用于创建对象的方法

方法名作用
T newInstance(Object... initargs)根据指定的构造方法创建对象
setAccessible(boolean flag)设置为true,表示取消访问检查
// 利用获取到的构造方法,创建类的对象
// 暴力反射:临时取消权限校验
conn8.setAccessible(true);
Student newInstance = (Student) conn8.newInstance("张三", 26);
System.out.println(newInstance);
// Student(name=张三, age=26)

四、使用反射获取成员变量

Student类:

@Data
public class Student {private String name;private int age;public String gender;public double store;public Student() {}public Student(String name, int age, String gender, double store) {this.name = name;this.age = age;this.gender = gender;this.store = store;}
}

(一)Class类中用于获取成员变量的方法

方法名作用
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象
Class clazz = Class.forName("com.testdemo.myreflect3.Student");
// 1.获取所有公共的成员变量
Field[] fields1 = clazz.getFields();
for (Field field : fields1) {System.out.println(field);
}
/*** public java.lang.String com.testdemo.myreflect3.Student.gender* public double com.testdemo.myreflect3.Student.store*/// 2.获取所有的成员变量
Field[] fields2 = clazz.getDeclaredFields();
for (Field field : fields2) {System.out.println(field);
}
/*** private java.lang.String com.testdemo.myreflect3.Student.name* private int com.testdemo.myreflect3.Student.age* public java.lang.String com.testdemo.myreflect3.Student.gender* public double com.testdemo.myreflect3.Student.store*/// 3.获取单个公共的成员变量
Field field3 = clazz.getField("gender");
System.out.println(field3);
// public java.lang.String com.testdemo.myreflect3.Student.genderField field4 = clazz.getField("store");
System.out.println(field4);
// public double com.testdemo.myreflect3.Student.store// 4.获取单个的成员变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);
// private java.lang.String com.testdemo.myreflect3.Student.nameField age = clazz.getDeclaredField("age");
System.out.println(age);
// private int com.testdemo.myreflect3.Student.ageField gender = clazz.getDeclaredField("gender");
System.out.println(gender);
// public java.lang.String com.testdemo.myreflect3.Student.genderField store = clazz.getDeclaredField("store");
System.out.println(store);
// public double com.testdemo.myreflect3.Student.store// 获取成员变量的权限修饰符
System.out.println(store.getModifiers()); // 1// 获取成员变量的名字
System.out.println(store.getName()); // store// 获取成员变量的数据类型
System.out.println(store.getType()); // double

(二)Field类中用于创建对象的方法

方法名作用
void set(Object obj, Object value)赋值
Object get(Object obj)获取值
// 获取成员变量记录的值
// 暴力反射:临时取消权限校验
name.setAccessible(true);
Student student = new Student("张三", 18, "男", 98.5);
String value = (String) name.get(student);
System.out.println(value); // 张三// 修改对象的属性值
name.set(student,"李四");
System.out.println(student);
// Student(name=李四, age=18, gender=男, store=98.5)

五、使用反射获取成员方法

Student类:

@Data
public class Student {private String name;private int age;public void sleep() {System.out.println("睡觉");}public void sleep(String someone) {System.out.println(someone + "在睡觉");}public void eat() {System.out.println("吃东西");}private String eat(String something) throws IOException, NullPointerException, ClassCastException {System.out.println("在吃" + something);return "菜单";}private void eat(String something, int a) {System.out.println("在吃" + something);}
}

(一)Class类中用于获取成员方法的方法

方法作用
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个成员方法对象
Class clazz = Class.forName("com.testdemo.myreflect4.Student");
// 1.获取所有公共的成员方法(包含父类中所有的公共方法)
Method[] methods = clazz.getMethods();
for (Method method : methods) {System.out.println(method);
}
/*** public java.lang.String com.testdemo.myreflect4.Student.getName()* public boolean com.testdemo.myreflect4.Student.equals(java.lang.Object)* public java.lang.String com.testdemo.myreflect4.Student.toString()* public int com.testdemo.myreflect4.Student.hashCode()* public void com.testdemo.myreflect4.Student.sleep()* public void com.testdemo.myreflect4.Student.sleep(java.lang.String)* public void com.testdemo.myreflect4.Student.setName(java.lang.String)* public void com.testdemo.myreflect4.Student.setAge(int)* public void com.testdemo.myreflect4.Student.eat()* public int com.testdemo.myreflect4.Student.getAge()* public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException* public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException* public final void java.lang.Object.wait() throws java.lang.InterruptedException* public final native java.lang.Class java.lang.Object.getClass()* public final native void java.lang.Object.notify()* public final native void java.lang.Object.notifyAll()* public void com.testdemo.myreflect4.Student.sleep(java.lang.String)*/// 2.获取所有的成员方法(不包含父类的成员方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod);
}
/*** public java.lang.String com.testdemo.myreflect4.Student.getName()* public boolean com.testdemo.myreflect4.Student.equals(java.lang.Object)* public java.lang.String com.testdemo.myreflect4.Student.toString()* public int com.testdemo.myreflect4.Student.hashCode()* public void com.testdemo.myreflect4.Student.sleep()* public void com.testdemo.myreflect4.Student.sleep(java.lang.String)* public void com.testdemo.myreflect4.Student.setName(java.lang.String)* public int com.testdemo.myreflect4.Student.getAge()* public void com.testdemo.myreflect4.Student.setAge(int)* protected boolean com.testdemo.myreflect4.Student.canEqual(java.lang.Object)* private void com.testdemo.myreflect4.Student.eat(java.lang.String,int)* public void com.testdemo.myreflect4.Student.eat()* private java.lang.String com.testdemo.myreflect4.Student.eat(java.lang.String) throws java.io.IOException,java.lang.NullPointerException,java.lang.ClassCastException* public void com.testdemo.myreflect4.Student.sleep(java.lang.String)*/// 3.获取单个公共的成员方法对象
Method sleep = clazz.getMethod("sleep", String.class);
System.out.println(sleep);
// public void com.testdemo.myreflect4.Student.sleep(java.lang.String)// 4.获取单个成员方法对象
Method eat = clazz.getDeclaredMethod("eat", String.class, int.class);
System.out.println(eat);
// private void com.testdemo.myreflect4.Student.eat(java.lang.String,int)Method eat1 = clazz.getDeclaredMethod("eat", String.class);
System.out.println(eat1);
// private java.lang.String com.testdemo.myreflect4.Student.eat(java.lang.String)
// throws java.io.IOException,java.lang.NullPointerException,java.lang.ClassCastException// 获取无参的成员方法
Method eat2 = clazz.getDeclaredMethod("eat");
System.out.println(eat2);
// public void com.testdemo.myreflect4.Student.eat()// 获取方法的修饰符
int modifiers = eat1.getModifiers();
System.out.println(modifiers); // 2// 获取方法的名字
String name = eat1.getName();
System.out.println(name); // eat// 获取方法的形参
Parameter[] parameters = eat1.getParameters();
for (Parameter parameter : parameters) {System.out.println(parameter);
}
// java.lang.String arg0// 获取方法抛出的异常
Class[] exceptionTypes = eat1.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {System.out.println(exceptionType);
}
/*** class java.io.IOException* class java.lang.NullPointerException* class java.lang.ClassCastException*/

(二)Method类中用于创建对象的方法

方法作用
Object invoke(Object obj, Object... args)

运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

// 方法运行
Student student = new Student();
eat1.setAccessible(true);
String result = (String) eat1.invoke(student, "汉堡包");
System.out.println(result);
// 在吃汉堡包
// 菜单

六、反射的作用

  1. 获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
  2. 结合配置文件,动态地创建对象并调用方法

(一)使用反射保存任意对象数据

对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去。

创建Cat类:

@Data
@AllArgsConstructor
public class Cat {private String ownerName;private String catName;private int age;private String breed;
}

创建Fish类:

@Data
@AllArgsConstructor
public class Fish {private int age;private String breed;
}

创建测试类:

public class TestDemo {public static void main(String[] args) throws IllegalAccessException, IOException {Cat cat = new Cat("张三", "咪咪", 2, "奶牛猫");Fish fish = new Fish(1, "鲤鱼");saveObjects(cat);saveObjects(fish);}private static void saveObjects(Object obj) throws IllegalAccessException, IOException {BufferedWriter bw = new BufferedWriter(new FileWriter("chapter19\\src\\com\\testdemo\\myreflect5\\a.txt",true));// 获取字节码文件的对象Class clazz = obj.getClass();// 获取所有的成员变量Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);// 获取属性名字String name = field.getName();// 获取属性值Object value = field.get(obj);// 写入文件bw.write(name + "=" + value);bw.newLine();}bw.close();}
}

运行结果:

(二)反射结合配置文件,动态地创建对象并调用方法

Student类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {private String name;private int age;public void study(){System.out.println("学生在学习!");}
}

Teacher类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {private String name;private double salary;public void teach() {System.out.println("老师在教书!");}
}

prop.properties:

classname=com.testdemo.myreflect6.Student
method=study

测试类:

public class MyReflectDemo {public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException {// 1.加载配置文件Properties properties = new Properties();FileInputStream fis = new FileInputStream("chapter19\\src\\com\\testdemo\\myreflect6\\prop.properties");properties.load(fis);fis.close();System.out.println(properties);// 2.获取全类名和方法名String classname = properties.getProperty(Constant.CLASS_NAME);String method = properties.getProperty(Constant.METHOD);// 3.获取字节码文件Class clazz = Class.forName(classname);// 4.获取构造方法Constructor constructor = clazz.getDeclaredConstructor();// 5.通过构造方法拿到对象Object obj = constructor.newInstance();System.out.println(obj);// Student(name=null, age=0)// 6.获取成员方法Method declaredMethod = clazz.getDeclaredMethod(method);// 6.1暴力反射:临时取消权限校验declaredMethod.setAccessible(true);// 7.执行成员方法:因为该成员方法是无参的,所以不需要传递第二个参数declaredMethod.invoke(obj);// 学生在学习!}
}interface Constant {String CLASS_NAME = "classname";String METHOD = "method";
}

要想创建Teacher对象,并调用Teacher的成员方法,只需要修改prop.properties文件中的配置信息即可:

classname=com.testdemo.myreflect6.Teacher
method=teach

修改配置文件后的运行结果:

Teacher(name=null, salary=0.0)
老师在教书!

http://www.mrgr.cn/news/59536.html

相关文章:

  • QT仿QQ聊天项目,第一节,创建项目并布置编辑登录界面
  • Pytorch学习--卷积操作
  • C语言程序设计:现代设计方法习题笔记《chapter6》上篇
  • 《使用Gin框架构建分布式应用》阅读笔记:p208-p211
  • <Project-11 Calculator> 计算器 0.3 年龄计算器 age Calculator HTML JS
  • uniapp路由权限拦截守卫
  • Python实现微博舆情分析的设计与实现
  • Pytest-Bdd-Playwright 系列教程(3):支持测试用例并行执行
  • python编程-闭包
  • 【unity】【游戏开发】Unity代码不给提示怎么办?
  • 租房业务全流程管理:Spring Boot系统应用
  • MTALAB guide 串口简洁版1
  • c++——哈希表的模拟实现
  • 关于Java中**optional,stream,lambda**
  • 特殊主题短视频资源推荐
  • 好用的骨传导运动耳机有哪些?2024年五款高口碑骨传导耳机分享
  • 100种算法【Python版】第14篇——Pollard‘s Rho 质因数分解算法
  • 10.Linux按键驱动-中断的线程化处理threadirq
  • 【LeetCode热题100】链表
  • 虚拟化平台
  • 《深入浅出HTTPS​​》读书笔记(2):HTTP
  • 【日常知识点】Java 语法糖,你用过几个?
  • 【日常知识点】到底推不推荐用JWT?
  • 007:点云处理软件TrimbleRealWorks12.0安装教程
  • 影刀RPA实战:验证码识别功能指令
  • 【系统架构设计师】案例分析预测试卷一(3道材料题)