Java#37(反射)

news/2024/11/27 23:49:32/

目录

一.反射的作用和关键

二. 反射获取对象

1.反射获取类对象

2.反射获取构造器对象 

3.反射获取成员变量对象

4. 反射获取方法对象

5.用反射绕过编译阶段为集合添加数据

反射做通用框架


一.反射的作用和关键

作用: 反射是在运行时获取类的字节码文件对象: 然后可以解析类中的全部成分
关键: 反射的核心思想和关键就是:得到编译以后的class文件对象

二. 反射获取对象

1.反射获取类对象

(1)使用 Class类中的静态方法

(2)使用 类名.class

(3)使用 对象.getClass( )

代码示范: 

package com.guaiwu;public class Test1 {public static void main(String[] args) throws ClassNotFoundException {//1.Class中forName(全限名:包名+类名)Class c = Class.forName("com.guaiwu.Student");System.out.println(c);//2.类名.classClass c1 = Student.class;System.out.println(c1);//3.对象.getClass()Student stu = new Student();Class c2 = stu.getClass();System.out.println(c2);}
}

结果展示: 

2.反射获取构造器对象 

使用反射技术获取构造器对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象

反射得到的构造器可以做什么?
依然可以创建对象
public newlnstance(Object... initargs)

如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
setAccessible(boolean)
反射可以破坏封装性,私有的也可以执行了
Class类中用于获取构造器的方法
                                        方法
Constructor<?>[ ] getConstructors()    返回所有构造器对象的数组 (只能拿public的)
Constructor<?>[ ] getDeclaredConstructors()返回所有构造器对象的数组,存在就能拿到
Constructor<T> getConstructor(Class<?>...parameterTypes)    返回单个构造器对象 (只能拿public的)
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)    返回单个构造器对象,存在就能拿到
代码示范:  第一段是测试类, 第二段是Student类

package com.guaiwu;import org.junit.jupiter.api.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.SQLOutput;public class TestStudent {@Testpublic void getDeclaredConstructors(){Class c1 = Student.class;System.out.println(c1);//getConstructor()和getDeclaredConstructor()的使用// Constructor con = c1.getConstructor();只能那public(比较局限)Constructor[] con1 = c1.getDeclaredConstructors();for (Constructor constructor : con1) {//构造方法的名字           参数数量System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());}System.out.println("=====================");}@Testpublic void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class c2 = Student.class;System.out.println(c2);//getConstructor()和getDeclaredConstructor()的使用//Constructor dcon = c2.getConstructor(String.class, int.class);只能那public(比较局限)Constructor dcon1 = c2.getDeclaredConstructor(String.class, int.class);System.out.println(dcon1.getName()+"--->"+dcon1.getParameterCount());//因为Student的有参构造是private,所以要先打开权限dcon1.setAccessible(true);//newInstance的返回类型是Object,所以要强转Student stu = (Student) dcon1.newInstance("张三", 90);System.out.println(stu);}
}
package com.guaiwu;public class Student {private String name;private int age;private Student() {}private Student(String name, int age) {this.name = name;this.age = age;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}

结果展示: 

3.反射获取成员变量对象

使用反射技术获取成员变量对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员变量的方法
                  方法                                                                   说明
Field[ ] getFields()                           返回所有成员变量对象的数组 (只能拿public的)
Fieldl getDeclaredFields()                 返回所有成员变量对象的数组,存在就能拿到
Field getField(String name)                   返回单个成员变量对象 (只能拿public的)
Field getDeclaredField(String name)     返回单个成员变量对象,存在就能拿到
Field类中用于取值、赋值的方法
void set(Object obj, Object value):          赋值
Object get(Object obj)                              获取值

代码示范:  第一段是测试类, 第二段是Student类

package com.guaiwu;import org.junit.jupiter.api.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;public class TestStudent {/*@Testpublic void getDeclaredConstructors(){Class c1 = Student.class;System.out.println(c1);//getConstructor()和getDeclaredConstructor()的使用// Constructor con = c1.getConstructor();只能那public(比较局限)Constructor[] con1 = c1.getDeclaredConstructors();for (Constructor constructor : con1) {//构造方法的名字           参数数量System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());}System.out.println("=====================");}@Testpublic void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class c2 = Student.class;System.out.println(c2);//getConstructor()和getDeclaredConstructor()的使用//Constructor dcon = c2.getConstructor(String.class, int.class);只能那public(比较局限)Constructor dcon1 = c2.getDeclaredConstructor(String.class, int.class);System.out.println(dcon1.getName()+"--->"+dcon1.getParameterCount());//因为Student的有参构造是private,所以要先打开权限dcon1.setAccessible(true);//newInstance的返回类型是Object,所以要强转Student stu = (Student) dcon1.newInstance("张三", 90);System.out.println(stu);System.out.println("=====================");}*/@Testpublic void getDeclaredFields(){//getFields()和getDeclaredFields()的使用//获取全部成员变量Class c3 = Student.class;Field[] DF = c3.getDeclaredFields();System.out.println(DF);for (Field field : DF) {System.out.println(field.getName()+"--->"+field.getType());}System.out.println("=====================");}@Testpublic void getDeclaredField() throws NoSuchFieldException, IllegalAccessException {Class c4 = Student.class;//获取类对象Field fieldName = c4.getDeclaredField("name");//获取某个成员变量//暴力打开权限fieldName.setAccessible(true);//获取一个Student类的对象Student stu = new Student();//使用set()方法fieldName.set(stu,"李四");String str = (String) fieldName.get(stu);System.out.println(str);System.out.println("=====================");}
}
package com.guaiwu;public class Student {private String name;private int age;public Student() {}private Student(String name, int age) {this.name = name;this.age = age;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}

结果展示: 

4. 反射获取方法对象

使用反射技术获取方法对象并使用
反射的第一步是先得到类对象,然后从类对象中获取类的成分对象
Class类中用于获取成员方法的方法
                      方法                                                  
Method[] getMethods()     返回所有成员方法对象的数组 (只能拿public的)
Method[] getDeclaredMethods()    返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name,Class<?>...parameterTypes)    返回单个成员方法对象 (只能拿public的)
Method getDeclaredMethod(String name, Class<?>... parameterTypes)      返回单个成员方法对象,存在就能拿到

Method类中用于触发执行的方法
                运行方法

Obiect invoke(Object obj,Object... args)
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

代码示范: 

package com.guaiwu;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Student{name = " + name + ", age = " + age + "}";}
}
package com.guaiwu;import org.junit.jupiter.api.Test;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class TestStudent {@Testpublic void getDeclaredMethods(){Class c5 = Student.class;Method[] mt1 = c5.getDeclaredMethods();for (Method method : mt1) {System.out.println(method.getName());}System.out.println("=====================");}@Testpublic void getDeclaredMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class c6 = Student.class;Method ts = c6.getDeclaredMethod("setName", String.class);ts.setAccessible(true);Student stu = new Student("wangwu",66);Object result = ts.invoke(stu,"maliu");System.out.println(result);System.out.println("=====================");}
}

结果示范: 

5.用反射绕过编译阶段为集合添加数据

原理: 编译成Class文件进入运行阶段的时候, 泛型会自动擦除

         反射是作用在运行时的技术, 此时已经不存在泛型了

代码示范: 

package com.guaiwu;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;public class Test1 {public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {ArrayList<Integer> list1 = new ArrayList<>();list1.add(123);list1.add(234);list1.add(345);//list1.add("加字符串会报错");//得到Class对象Class c1 = list1.getClass();//getDeclaredMethod获取对应的方法Method add1 = c1.getDeclaredMethod("add", Object.class);//通过invoke执行方法//另一种方式add1.invoke(list1,"现在可以加任意类型");System.out.println(list1);ArrayList list2 = list1;list2.add("ture");System.out.println(list1);}
}

结果展示: 

 

反射做通用框架

练习: 给你任意一个对象,在不清楚对象字段的情况可以,可以把对象的字段名称和对应值存储到文件中去

代码示范: 第一,第二段是类的代码, 第三段是通用框架的代码(重点), 第四段是测试代码

package com.guaiwu;public class Teacher {private String name;private int age;private String schoolName;private String hobby;public Teacher() {}public Teacher(String name, int age, String schoolName, String hobby) {this.name = name;this.age = age;this.schoolName = schoolName;this.hobby = hobby;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return schoolName*/public String getSchoolName() {return schoolName;}/*** 设置* @param schoolName*/public void setSchoolName(String schoolName) {this.schoolName = schoolName;}/*** 获取* @return hobby*/public String getHobby() {return hobby;}/*** 设置* @param hobby*/public void setHobby(String hobby) {this.hobby = hobby;}public String toString() {return "Teacher{name = " + name + ", age = " + age + ", schoolName = " + schoolName + ", hobby = " + hobby + "}";}
}
package com.guaiwu;public class Student {private String name;private int age;private String schoolName;private String hobby;public Student() {}public Student(String name, int age, String schoolName, String hobby) {this.name = name;this.age = age;this.schoolName = schoolName;this.hobby = hobby;}/*** 获取* @return name*/public String getName() {return name;}/*** 设置* @param name*/public void setName(String name) {this.name = name;}/*** 获取* @return age*/public int getAge() {return age;}/*** 设置* @param age*/public void setAge(int age) {this.age = age;}/*** 获取* @return schoolName*/public String getSchoolName() {return schoolName;}/*** 设置* @param schoolName*/public void setSchoolName(String schoolName) {this.schoolName = schoolName;}/*** 获取* @return hobby*/public String getHobby() {return hobby;}/*** 设置* @param hobby*/public void setHobby(String hobby) {this.hobby = hobby;}public String toString() {return "Student{name = " + name + ", age = " + age + ", schoolName = " + schoolName + ", hobby = " + hobby + "}";}
}
package com.guaiwu;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;public class MybatisUtil {//保存任意类型的对象public static void save(Object obj) throws IllegalAccessException, FileNotFoundException {PrintStream ps = new PrintStream(new FileOutputStream("D:\\Java\\java\\Demo1_12_14\\src\\com\\guaiwu\\a.txt",true));//得到类对象Class c1 = obj.getClass();ps.println("========="+c1.getSimpleName()+"=========");//得到类的全部成员变量Field[] fields = c1.getDeclaredFields();//遍历集合for (Field field : fields) {String name = field.getName();//取值field.setAccessible(true);//打开权限String value = field.get(obj) + "";ps.println(name+"="+value);}}
}
package com.guaiwu;import java.io.FileNotFoundException;public class Demo1 {public static void main(String[] args) throws FileNotFoundException, IllegalAccessException {Student stu = new Student("张三",66,"小学","睡觉");Teacher tea = new Teacher("李四",99,"小学","打羽毛球");MybatisUtil.save(stu);MybatisUtil.save(tea);}
}

结果展示: 

 


http://www.ppmy.cn/news/3449.html

相关文章

看看阿里程序员是怎样讲限流的

限流算法很多,常见的有三类,分别是计数器算法、漏桶算法、令牌桶算法,下面逐一讲解。 计数器算法 简单粗暴,比如指定线程池大小&#xff0c;指定数据库连接池大小、nginx连接数等,这都属于计数器算法。 计数器算法是限流算法里最简单也是最容易实现的一种算法。举个例子,比如…

大数据时代,数据实时同步解决方案的思考—最全的数据同步总结

F、 客户端开发&#xff0c;在maven中引入canal的依赖 com.alibaba.otter canal.client 1.0.21 代码示例&#xff1a; package com.example; import com.alibaba.otter.canal.client.CanalConnector; import com.alibaba.otter.canal.client.CanalConnectors; import c…

java swing(GUI) MySQL实现的学生选课签到考勤系统源码开发教程

今天给大家演示一款由Java swing即GUI和mysql数据库实现的&#xff0c;学生签到考勤信息管理系统&#xff0c;系统采用了MVC的设计模式&#xff0c;结构层次非常清晰&#xff0c;此外&#xff0c;该项目有手把手的开发教程&#xff0c;适合刚入门Java的学生学习&#xff0c;下面…

android aidl使用demo

android使用aidl原理 参考链接: https://www.twle.cn/l/yufei/android/android-basic-service-aidl.html 通过这部分代码, 加深对Android AIDL的理解 aidl server端 ILanguage.aidl 步骤: 在main目录下创建aidl文件夹, 并创建对应的包 com.example.aidl, 然后创建ILanguage.ai…

Microsoft SharePoint Online 更新功能可能是下一次勒索攻击的目标

Microsoft SharePoint Online是被使用最广泛的内容管理平台之一。但令人担忧的是&#xff0c;最近几年我们发现大部分攻击者可以滥用 SharePoint Online 和 OneDrive for Business 中的某项功能来加密您的所有文件并以此来勒索赎金。 SharePoint Online 据观察发现可能存在潜在…

【云计算与大数据技术】资源管理、调度模型策略的讲解

一、资源管理模型 集群资源管理模型通常由两个部分组成&#xff0c;即资源表示模型和资源分配模型&#xff0c;由于这两个部分是耦合的&#xff0c;所有优化集群资源管理时需要同时结合这两个部分考虑&#xff0c;资源表示模型用于描述集群资源的组织方式&#xff0c;是集群资…

大数据Kudu(五):Kudu基于Cloudera Manager安装及配置

文章目录 Kudu基于Cloudera Manager安装及配置 一、启动CM集群 二、登录ClouderaManager平台安装Kudu

性能测试知识之三大模型

今天的这篇文章我会聊聊在实际工作中开展性能测试&#xff0c;前期最核心的工作。即业务模型、流量模型和数据模型这三大模型&#xff0c;该如何评估和建立。在性能测试工作中&#xff0c;业务模型、流量模型和数据模型是至关重要且必须在项目中构建的&#xff0c;否则很可能导…