反射的概念|反射的概念 和基本使用(一)

1 反射 什么是反射

java反射 是指在运行状态中 对于任意一个类 我们都可以知到这个类的所有方法和属性 也可以调用其所有的方法和属性 这种动态获取的方式 我们称为 反射
什么是class对象
反射的概念|反射的概念 和基本使用(一)
文章图片

我们通过使用反射 就是通过Class类来实现的 Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
反射的使用
获取class对象的三种方式 基本类
/** * * @author : look-word * @date : 2022-04-05 20:49 **/ public class Student { private String username; private String gender; publicString getInfo() { this.setUsername("张三"); this.setGender("男"); return this.username+"="+this.gender; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }public String getGender() { return gender; }public void setGender(String gender) { this.gender = gender; } }

测试代码如下
/** * @author : look-word * @date : 2022-04-05 20:54 **/ public class Test { public static void main(String[] args) {/* 1 创建对象 获取其class对象 */ Student student = new Student(); Class aClass = student.getClass(); System.out.println(aClass.getSimpleName()); /* 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性 */ Class bClass=Student.class; System.out.println(aClass == bClass?"两者是同一对象":"两者不是同一对象"); /* 3 通过Class类的forName方法获取 */ try { //Class.forName(类的相对路径) Class cClass = Class.forName("bean.Student"); System.out.println(bClass == cClass?"两者是同一对象":"两者不是同一对象"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }

结果如下 【反射的概念|反射的概念 和基本使用(一)】反射的概念|反射的概念 和基本使用(一)
文章图片

证明
在运行期间 一个类只有一个class对象的产生
常用的是第三次 清晰 明了 因为 在一个项目中 可能会产生 相同名字的类
解决疑惑 为什么要是用 第三种
第一种对象都有了还要反射干什么。
第二种需要导入类的包,依赖太强,不导包就抛编译错误。
第三种,一个字符串可以传入也可写在配置文件中等多种方法。
获取Class类中的所有构造方法 基本类
public class Student { //---------------构造方法------------------- //(默认的构造方法) Student(String str){ System.out.println("(默认)的构造方法 s = " + str); }//无参构造方法 public Student(){ System.out.println("调用了公有、无参构造方法执行了。。。"); }//有一个参数的构造方法 public Student(char name){ System.out.println("姓名:" + name); }//有多个参数的构造方法 public Student(String name ,int age){ System.out.println("姓名:"+name+" 年龄:"+ age); //这的执行效率有问题,以后解决。 }//受保护的构造方法 protected Student(boolean n){ System.out.println("受保护的构造方法 n = " + n); }//私有构造方法 private Student(int age){ System.out.println("私有的构造方法年龄:"+ age); } }

测试代码
/** * 测试构造方法 * @author : look-word * @date : 2022-04-05 21:18 **/ public class TestConstructor {/** * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员; * * 1.获取构造方法: *1).批量的方法: *public Constructor[] getConstructors():所有"公有的"构造方法 public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有) *2).获取单个的方法,并调用: *public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法: *public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有; * *调用构造方法: *Constructor-->newInstance(Object... initargs) */ public static void main(String[] args) throws Exception { Class student = Class.forName("bean.Student"); /* 1 获取所有共有的构造方法 */ System.out.println("\n1 获取所有共有的构造方法"); Constructor[] constructors = student.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); }/* 2 获取共有的无参构造方法 可以写 null 或者 不填 */ System.out.println("\n2 获取共有的无参构造方法 可以写 null 或者 不填"); Constructor constructor2 = student.getConstructor(); constructor2.newInstance(); /* 3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int) */ System.out.println("\n 3 获取 给定参数共有的构造方法 public bean.Student(java.lang.String,int)"); Constructor constructor3 = student.getConstructor(String.class, int.class); constructor3.newInstance("张三",19); /* 4 获取 私有给定参数的构造方法 私有 不给定参数 不传参数即可 */ Constructor constructor4 = student.getDeclaredConstructor(int.class); /* 获取私有的属性 或者构造方法是 需要 设置无障碍 俗称 暴力访问 不设置 会出异常 java.lang.IllegalAccessException */ constructor4.setAccessible(true); constructor4.newInstance(19); } }

执行结果 反射的概念|反射的概念 和基本使用(一)
文章图片

注意
获取私有属性的时候 一定要设置无障碍
setAccessible(true);
不设置 会出异常 java.lang.IllegalAccessException
newInstance(Object... initargs) 创建一个新实例
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
每次是用 newInstance创建的对象 都是不同的对象 代表不同的实例
操作成员变量 基本类
public class Student { public Student(){ } //**********字段*************// public String name; protected int age; char sex; private String phoneNum; @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", phoneNum=" + phoneNum + "]"; } }

测试代码
/** * @author : look-word * @date : 2022-04-05 21:55 **/ public class TestField {/* * 获取成员变量并调用: * * 1.批量的 *1).Field[] getFields():获取所有的"公有字段" *2).Field[] getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有; * 2.获取单个的: *1).public Field getField(String fieldName):获取某个"公有的"字段; *2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的) * *设置字段的值: *Field --> public void set(Object obj,Object value): *参数说明: *1.obj:要设置的字段所在的对象; *2.value:要为字段设置的值; */ public static void main(String[] args) throws Exception{ Class aClass = Class.forName("bean.Student"); Student student = new Student(); /* 获取所有的共有字段 */ System.out.println("-------------------获取所有的共有字段--------------------"); Field[] fields = aClass.getFields(); for (Field field : fields) { /* filed => public java.lang.String bean.Student.username filed => 成员变量 *//* 我理解为 给某个对象的 成员变量 赋值 当前的filed 为 username 因为这里只能获取为 共有属性的成员变量 * field.set(student,"zhangsan"); */ field.set(student,"zhangsan"); System.out.println(student); /* field.get(student); 获取某student中的 field 的 内容 */ Object o = field.get(student); System.out.println(o); /* *打印filed的内容 => public java.lang.String bean.Student.username */ System.out.println(field); }System.out.println("-------------------给私有字段赋值--------------------"); Field phone = aClass.getDeclaredField("phone"); phone.setAccessible(true); // 设置无障碍 phone.set(student,"110"); // 赋值给student对象System.out.println("-------------------获取私有字段--------------------"); Field phone1 = aClass.getDeclaredField("phone"); phone1.setAccessible(true); // 设置无障碍 System.out.println(phone1.get(student)); //取出student对象中的phone属性的值 } }

注意
在操作私有属性的时候 不管是获取还是设置值 都需要设置无障碍
setAccessible(true); // 设置无障碍

    推荐阅读