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

首页 / 新闻资讯 / 正文

什么是反射

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;      public  String 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<? extends Student> aClass = student.getClass();         System.out.println(aClass.getSimpleName());         /*             2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性          */         Class<? extends Student> 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);// 设置无障碍

Top