反射的作用( 越过泛型检查 和 可以使用反射保存所有对象的具体信息 )

news/2024/5/19 6:19:05 标签: 反射, getClass(), invoke()

1、绕过 编译阶段 为集合添加数据

  • 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以 为集合存入其他任意类型的元素的
  • 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在 编译成Class文件进入 运行阶段 的时候,其真实类型都是不带泛型的集合,泛型相当于被擦除了。
package com.csdn.d6_reflect_genericity;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class ReflectDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //需求:反射实现泛型擦除后,加入其他类型的元素
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();

        System.out.println(list1.getClass());//class java.util.ArrayList
        System.out.println(list2.getClass());//class java.util.ArrayList

        System.out.println(list1.getClass() == list2.getClass());//true

        System.out.println("===============================");

        ArrayList<Integer> list3 = new ArrayList<>();
        list3.add(23);
        list3.add(22);

        Class<? extends ArrayList> aClass = list3.getClass();

        Method add = aClass.getDeclaredMethod("add", Object.class);
        boolean rs = (boolean) add.invoke(list3, "反射");
        System.out.println(rs);//true

        System.out.println(list3);//[23, 22, 反射]

        ArrayList list4 = list3;
        list4.add("注解");
        list4.add(false);
        System.out.println(list3);//[23, 22, 反射, 注解, false]

    }
}

1.1、反射为何可以给约定了泛型的集合存入其他类型的元素?

  • 编译成Class文件进入运行阶段 的时候,泛型会自动擦除
  • 反射是作用在 运行时 的技术,此时已经不存在泛型了 。

 2、通用框架的底层原理

需求

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

分析

  1. 定义一个 方法 ,可以接收任意类的对象
  2. 每次收到一个对象后,需要解析这个对象的 全部成员变量名称
  3. 这个对象可能是 任意 的,那么怎么样才可以知道这个对象的全部成员变量名称呢
  4. 使用 反射 获取对象的 Class类对象 ,然后获取全部成员变量信息
  5. 遍历成员变量信息,然后提取本成员变量在对象中的 具体值
  6. 存入成员变量名称和值到 文件 中去即可
package com.csdn.d7_reflect_framework;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
/**
 * 目标:提供一个通用框架,支持保存所有对象的具体信息。
 */
public class ReflectDemo {
    public static void main(String[] args) {
        Student student = new Student("反射", '男', 100, "JavaSE", "暴力访问");
        MybatisUtil.save(student);

        Teacher teacher = new Teacher("注解", '女', 10000);
        MybatisUtil.save(teacher);
    }
}

class MybatisUtil {
    public static void save(Object object) {
        try {
            try (PrintStream ps = new PrintStream(new FileOutputStream("reflect\\src\\main\\java\\com\\csdn\\d7_reflect_framework\\object.txt",true))) {
                //1、提取这个对象的全部成员变量:只能反射可以解决
                Class<?> aClass = object.getClass();
                ps.println("==============" + aClass.getSimpleName() + "================");

                //2、提取它的全部成员变量
                Field[] fields = aClass.getDeclaredFields();
                //3、获取成员变量的信息
                for (Field field : fields) {
                    String name = field.getName();
                    //提取本成员变量的object对象中的值(取值)
                    field.setAccessible(true);

                    String value = field.get(object) + "";

                    ps.println(name + "=" + value);

                }
            }
        } catch (IllegalAccessException | FileNotFoundException e) {
            throw new RuntimeException(e);
        }

    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Student {
    private String name;
    private char sex;
    private int age;
    private String className;
    private String hobby;
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Teacher {
    private String name;
    private char sex;
    private double salary;
}

 

 3、反射的作用?

  • 可以在运行时得到一个 类的 全部成分 然后操作
  • 可以 破坏封装性(很突出)
  • 也可以 破坏泛型的约束性(很突出)
  • 更重要的用途是适合:做 Java 高级框架

http://www.niftyadmin.cn/n/5113444.html

相关文章

Day7力扣打卡

打卡记录 合法分组的最少组数&#xff08;贪心&#xff09; 链接 举例说明&#xff0c;假设 c n t [ x ] 32 cnt[x]32 cnt[x]32&#xff0c; k 10 k10 k10&#xff0c;那么 32 10 10 10 2 321010102 321010102&#xff0c;多出的 2 2 2 可以分成两个 1 1 1&#xf…

MySQL 的 ORDER BY 排序内部原理

在 MySQL 中&#xff0c;ORDER BY 子句用于对查询结果进行排序。排序的内部原理涉及 MySQL 的查询执行过程和索引结构。以下是 MySQL 中 ORDER BY 排序的基本原理&#xff1a; 查询执行计划&#xff1a;执行一个 SQL 查询&#xff0c;MySQL 的查询优化器会生成一个查询执行计划…

力扣每日一题59:螺旋矩阵||

题目描述&#xff1a; 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&am…

torch.jit.trace与torch.jit.script

Script mode通过torch.jit.trace或者torch.jit.script来调用。这两个函数都是将python代码转换为TorchScript的两种不同的方法。 torch.jit.trace将一个特定的输入&#xff08;通常是一个张量&#xff0c;需要我们提供一个input&#xff09;传递给一个PyTorch模型&#xff0c;…

中间件安全-CVE复现WeblogicJenkinsGlassFish漏洞复现

目录 服务攻防-中间件安全&CVE复现&Weblogic&Jenkins&GlassFish漏洞复现中间件-Weblogic安全问题漏洞复现CVE_2017_3506漏洞复现 中间件-JBoos安全问题漏洞复现CVE-2017-12149漏洞复现CVE-2017-7504漏洞复现 中间件-Jenkins安全问题漏洞复现CVE-2017-1000353漏…

C#中ThreadPool线程池的使用总结

使用线程池&#xff0c;可以通过向应用程序提供由系统管理的工作线程池&#xff0c;来更有效地使用线程。托管线程池中的线程是后台线程。 其 IsBackground 属性为 true。线程池可以减少资源损耗。重用线程、控制线程数量&#xff0c;减少线程创建和切换所带来的开销。提高响应…

Windows 安装 Java

1. 安装 JDK 从 Oracle 的官网下载的 JDK&#xff0c;例如 JDK 21 双击下载得到的 msi 文件&#xff0c;开始安装 JDK 选择要安装的文件路径&#xff08;我一般都默认&#xff09;&#xff1a; 等待安装&#xff1a; 安装完成&#xff1a; 2. 验证是否安装成功 2.1. 打开 cmd…

【JavaEE】Java的文件IO

文件IO操作 Linux 下的文件操作讲解Java中的文件操作 -- 对文件的增删改查Java中对文件内容的操作 -- 读写操作使用案例 Linux 下的文件操作讲解 在我的Linux栏目下有, 如有需要, 点击下面进行跳转: 内存级文件系统语言级别的文教操作磁盘文件 Java中的文件操作 – 对文件的…