Java-反射
2024-01-01 10:34:36
一、什么是反射?
反射允许对封装类的成员变量,成员方法和构造方法的信息进行编程访问。
反射可以把成员变量、成员方法、构造方法挨个儿的都获取出来,并对它们进行操作。
IDEA中自动提示的功能就是用反射来做的。
Ctrl+p:快捷键,获取方法的形参,也是利用的反射。
- 反射可以获取类中的成员变量、成员方法、构造方法。获取是从Class字节码文件中获取的。
- 反射可以解刨成员变量、成员方法、构造方法中的信息。
先获取Class对象,再从Class对象中获取成员变量、成员方法、构造方法,再去解刨获取其中的每一个具体的信息。
二、获取class对象的三种方式
- Class.forName(“全类名”);
- 类名.class;
- 对象.getClass();
三种方式的使用场景:
//第一种方式(最常用)
Class clazz1 = Class.forName("myreflect.Student");
//第二种方式(一般当做参数进行传递)
Class clazz2 = Student.class;
//第三种方式(有这个类的对象的时候使用)
Student s = new Student();
Class clazz3 = s.getClass();
三、反射获取构造方法
在Java中万物皆对象
例如:Constructor类的对象就是构造方法的对象。
Student类中的内容:
package myreflect;
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 String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试反射类中的主要内容:
//1、获取class字节码文件对象
Class clazz = Class.forName("myreflect.Student");
//2、返回所有公共构造方法对象的数组
Constructor[] cons1 = clazz.getConstructors();
for (Constructor con : cons1) {
System.out.println(con);
}
System.out.println("-------------");
//3、返回所有构造方法的数组
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
System.out.println("-------------");
//4、返回单个公共构造方法对象
Constructor con1 = clazz.getConstructor(String.class);
System.out.println(con1);
System.out.println("-------------");
//5、获取private修饰的构造方法
Constructor con2 = clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(con2);
System.out.println("-------------");
//6、获取权限修饰符,是通过整数的形式来体现的。
int modifiers = con2.getModifiers();
System.out.println(modifiers);
System.out.println("-------------");
//7、利用反射创建对象
con2.setAccessible(true); //表示临时取消权限校验(暴力反射)
Student stu = (Student) con2.newInstance("赵六", 28);
System.out.println(stu);
权限修饰符所对应的数字:
四、反射获取成员变量
Student类中的内容:
package myreflect2;
public class Student {
private String name;
private int age;
public String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
测试类中的主要内容:
package myreflect2;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1、获取class字节码对象
Class clazz = Class.forName("myreflect2.Student");
//2.1、获取所有公共的成员变量
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
//2.2、获取所有的成员变量
System.out.println("-------");
Field[] fields2 = clazz.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
//3.1、获取单个的成员变量(公共的)
System.out.println("-------");
Field gender = clazz.getField("gender");
//3.2、获取单个的成员变量
System.out.println("-------");
Field name = clazz.getDeclaredField("name");
//4、获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
//5、获取成员变量的名字
System.out.println("-------");
String name1 = name.getName();
System.out.println(name1);
//6、获取成员变量的数据类型
System.out.println("-------");
Class<?> type = name.getType();
System.out.println(type);
//7、获取成员变量记录的值
System.out.println("-------");
Student stu = new Student("zhansan",14,"nan");
name.setAccessible(true); //临时取消权限校验
Object o = name.get(stu);
System.out.println(o);
//8、修改对象里面记录的值
System.out.println("-------");
name.set(stu,"zhaoliu");
System.out.println(stu);
}
}
五、反射获取成员方法
Student类中的内容:
package myreflect3;
import java.io.IOError;
import java.io.IOException;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void sleep(){
System.out.println("睡觉");
}
private String eat(String something) throws IOException,IndexOutOfBoundsException{
System.out.println("在吃" + something);
return "吃饱了";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类中的内容:
package myreflect3;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1、获取class字节码文件对象
Class clazz = Class.forName("myreflect3.Student");
//2、获取所有公共的方法对象(包含父类中所有的公共方法)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
//3、获取里面所有方法对象(不包含父类的 但是 可以获取本类中私有的成员方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
//4、获取指定的单一方法
//第一个参数:方法的名称
//第二个参数:方法中形参的类型(具备形参的类型是考虑到方法重载的问题)
Method eat = clazz.getDeclaredMethod("eat", String.class);
//5、获取方法的修饰符
int modifiers = eat.getModifiers();
System.out.println(modifiers);
//6、获取方法的名字
String name = eat.getName();
System.out.println(name);
//7、获取方法的形参
Parameter[] parameters = eat.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//8、获取方法抛出的异常
Class[] exceptionTypes = eat.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//9、运行方法
Student stu = new Student();
eat.setAccessible(true);
eat.invoke(stu,"米饭"); //第一个参数是对象,第二个参数是eat方法中要传递的值
//用 stu对象 去调用 其中的 eat方法 传递的参数 是 "米饭"。
//10、获取方法的返回值
String result = (String) eat.invoke(stu, "小米粥");
System.out.println(result);
}
}
六、反射的作用
1、获取一个类里面的所有的信息,获取到之后,再执行其他的业务逻辑
2、结合配置文件,动态的创建对象并调用方法。
七、练习一
保存信息:对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去。
主要代码:
package myreflect4;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) throws IllegalAccessException, IOException {
//对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去。
Student stu = new Student("小n",23,'女',168.5f,"玩游戏");
Teacher t = new Teacher("zhangsan",10000);
saveObject(stu);
}
//把对象里面所有的成员变量名和值保存到本地文件中
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//获取字节码文件的对象
Class clazz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
//获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
//取消临时权限校验
declaredField.setAccessible(true);
//获取变量的名字
String name = declaredField.getName();
//获取变量中的值
Object value = declaredField.get(obj);
//写入文件中数据
bw.write(name+"="+value);
//写一行,换一行
bw.newLine();
}
bw.close();
}
}
八、练习二
反射可以和配置文件相结合,动态的创建对象,并调用方法
Student类中内容:
package myreflect5;
public class Student {
private String name;
private int age;
public void study(){
System.out.println("学生在学习!");
}
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Teacher类中内容:
package myreflect5;
public class Teacher {
private String name;
private int salary;
public Teacher() {
}
public void teach(){
System.out.println("老师在教书!");
}
public Teacher(String name, int salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", salary=" + salary +
'}';
}
}
prop.properties文件中内容:
classname=myreflect5.Teacher
method=teach
测试类中内容:
package myreflect5;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class Demo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1、读取配置文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("prop.properties");
prop.load(fis);
fis.close();
System.out.println(prop);
//2、获取全类名和方法名
String className = (String) prop.get("classname");
String methodName = (String) prop.get("method");
System.out.println(className);
System.out.println(methodName);
//3、利用反射创建对象并运行方法
Class clazz = Class.forName(className);
//4、获取构造方法
Constructor con = clazz.getDeclaredConstructor();
Object o = con.newInstance();
System.out.println(o);
//5、获取成员方法并运行
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);
method.invoke(o);
}
}
九、总结
power by 黑马
文章来源:https://blog.csdn.net/qq_48269763/article/details/135321200
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!