首页 > 其他分享 >反射及其应用---->2

反射及其应用---->2

时间:2024-09-29 09:21:42浏览次数:11  
标签:反射 int Object ---- 应用 使用 泛型 Class 加载

目录

1.使用类对象

1.1创建对象

1.2使用对象属性

1.3使用方法

2.反射操作数组

3.反射获得泛型

4.类加载器

4.1双亲委派机制

4.2自定义加载器


1.使用类对象

  • 通过反射使用类对象,主要体现3个部分

  • 创建对象,调用方法,调用属性(存值,取值)

1.1创建对象

利用反射创建对象有两种方式

  1. 通过构造器创建对象(推荐)

  2. 通过Class直接创建对象(只支持利用无参构造器创建对象)

Object o = c.newInstance(); //使用无参构造器创建对象

Constructor con = c.getConstructor(int.class, int.class);
//A a = new A(10,20);
Object o = con.newInstance(10, 20);

1.2使用对象属性

  • 包括使用属性赋值, 使用属性取值。

  • 需要先获得要操作的属性对象

Object a1 = c.newInstance();

Field n = c.getField("n"); //获得的public的属性

n.set(a1,"XXXX");

Object value = n.get(a1);
System.out.println(value);
//私有属性,可以通过设置i.setAccessible(true) 实现对私有成员的访问
//注意1: 使用后,建议将其重新锁住  i.setAccessible(false)
//注意2: 强烈不推荐使用该方式操作私有成员,建议通过封装,提供对应的get和set方法。
Field i = c.getDeclaredField("i");
i.setAccessible(true);
i.set(null,100); //传递null,是因为i属性是一个static属性
Object value = i.get(null);
System.out.println(value);
i.setAccessible(false);
  • 在jdk1.9之后,对java中的类库做了重新的处理

  • 增加了一个模块的功能,成员属于类,类属于包,包属于模块, 模块属于程序

    • 包中的类需要export导出,其他模块中的类才可见。

    • 包中未导出的类,其他模块中的类不可见,不可引入,不可反射操作

    • 当然,可以通过jvm参数配置,使得模块中的内容都可以反射操作。

1.3使用方法

反射调用对象的方法,需要先获得对应的Method方法对象

  • 获得Method对象时,除了指定方法名,还需要指定方法的参数列表(Class)

  • 调用方法时,需要指定所属对象(static方法所属null或Class),需要传递具体的参数值(Object)

Object a = c.newInstance();
Method m = c.getMethod("t1", int.class, int.class);//t1(int,int)
//a.t1(100,200);
Object r = m.invoke(a, 100, 200);
Method m = c.getDeclaredMethod("t2");//t2()
m.setAccessible(true);
m.invoke(a) ;
m.setAccessible(false);

2.反射操作数组

反射操作数组,使用的是Array类

//Object array = new int[5];
//array[1] (取值, 赋值)
Object array = Array.newInstance(int.class, 5);

Array.set( array , 0 , 250 );

Object value = Array.get(array, 0);
System.out.println(value);

int len = Array.getLength(array);
System.out.println(len);

3.反射获得泛型

关于反射获得泛型,有两种操作需求

  1. 获得类定义时的泛型 T , V , K , E

public static void t1(){
    Class c = A.class;
    TypeVariable[] typeParameters = c.getTypeParameters();//类定义时的泛型
    System.out.println(typeParameters.length);
    System.out.println(typeParameters[0].getName());
}

    2.获得类使用时的泛型,具体的类型 List<String>

public static void t2() throws NoSuchFieldException, NoSuchMethodException {
    Class c = B.class ;
    Field a = c.getDeclaredField("a");
    Type type = a.getGenericType();
    
    //一般getGeneric系列,都是用来获得所包含的泛型的。
    //(属性类型,返回类型,参数类型,父类型,父接口类型)都有该系列方法
    //Class is a Type  
    //泛型类型,也称为参数化类型 is a Type , 本质是 ParameterizedType
    ParameterizedType pt = (ParameterizedType) type;
    
    //Type[] pts = pt.getActualTypeArguments(); //获得多个泛型的数组
    Type rawType = pt.getRawType();//获得泛型类型

}

4.类加载器

  • JVM在运行程序时,会使用类加载器,加载(读取)类文件的信息,并对其进行一系列的处理,最终将其存储在方法区,并生成与之对应的Class对象。

  • 类信息有不同的情况

    • 有我们自己的写的类信息

    • 有jdk自带的类信息

    • 未来可能还有其他的类信息,如:网络中的类信息,需要加密处理类信息等。

  • jdk针对于不同的类信息情况,提供了不同的类加载器,默认有3种

    1. BootstrapClassLoader 启动类加载器,使用C/C++实现,加载jdk基本类库,如:java.lang等

    2. ExtClassLoader 扩展类加载器,使用Java实现的,加载jdk扩展类库

    3. AppClassLoader 应用类加载器,使用Java实现的,classpath路径中的类,我们自己编写的类

4.1双亲委派机制

  • jdk提供了3个加载器,未来我们还能自定义加载器

  • jdk同时提供了双亲委派机制,使得多个加载器可以更合理的协作应用

    1. 当我们在程序中需要使用一个类时,会先向最底层的类加载器申请这个类(app)

    2. 如果app加载器加载过这个类,就会返回该类的Class对象

    3. 如果app没有加载过这个类,app会向其父级加载器(ext)申请这个类

    4. 如果ext加载过就返回这个类,如果没有加载过这个类,继续想起父级(Bootstrap)申请

    5. 如果bootstrap加载过就返回这个类,如果没有加载过,就尝试加载

    6. 如果在bootstrap的加载范围内,则加载这个类

    7. 如果不再bootstrap的加载范围内, 尝试让ext加载

    8. 如果在ext加载范围内,就让ext加载。如果不在就尝试让app加载

    9. 如果在app加载范围内,就让app加载,否则就抛出ClassNotFoundException

  • 注意:app 和 ext 和 bootstrap是逻辑上的子父级关系,不是真正 的extends继承关系

  • 双亲委派机制的优点

    1. 防止核心类被篡改。

    2. 方式类重复加载

    3. 防止在核心包中扩展类(沙箱机制)

4.2自定义加载器

  • 哪些情况需要自定义类加载器呢?

    1. 扩展加载源 ,如:从网络中加载类库

    2. 类的隔离

    3. 类信息的解密

  • 如何自定义类加载器

    1. 自定义加载器类, 继承ClassLoader

    2. 重写方法

      • 可以重写loadClass方法,但不推荐。因为该方法中提供了双亲委派机制

        如果重写该方法,相等于破坏了双亲委派机制。

      • 可以重写findClass方法,根据需求,去指定的地方获取类文件信息

        以byte[]的形式装载找到的类信息

      • 还有一个很重要的方法defineClass(),用来将字节码内容进行一系列的处理,并存储在方法区,并生成Class对象

        所以在findClass之后,一定要调用该方法。

    3. 使用类加载器

public class MyClassLoader extends ClassLoader{

    //name 一般就是com.buka.User 类路径
    //可以根据这个类路径确定最重要加载的目标类
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            Socket link = new Socket("localhost",6666);
            InputStream is = link.getInputStream();
            //存储所有读取到的字节信息
            //本来是需要使用字节数组
            //但无法确定从网络中读取字节的数量,就不知道要定义多长的字节数组
            //可以使用ByteArrayOutputStream
            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            byte[] bs =new byte[010];
            while(true){
                int len = is.read(bs);
                if(len == -1){
                    break ;
                }
                bos.write(bs,0,len);
            }

            byte[] content = bos.toByteArray();

           return  super.defineClass("X",content,0,content.length);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
    MyClassLoader loader  = new MyClassLoader();
    Class<?> c = loader.loadClass("X");
    c.newInstance();
}

标签:反射,int,Object,----,应用,使用,泛型,Class,加载
From: https://blog.csdn.net/lzp122390/article/details/142627110

相关文章

  • 【含文档+PPT+源码】基于SpringBoot的体育馆管理系统的设计与实现
    项目背景与意义近年来,随着人们生活水平的提高和健康意识的增强,体育馆作为提供体育锻炼和休闲娱乐的重要场所,其使用频率和管理难度也在不断增加。传统的体育馆管理模式通常依赖于人工记录和手动操作,不仅效率低下,而且容易出现错误和遗漏,难以适应现代社会的快节奏和高效率要求。......
  • 搜索:如何用 A*搜索算法实现游戏中的寻路功能?
    搜索:如何用A*搜索算法实现游戏中的寻路功能?在游戏开发中,寻路功能是一个非常重要的部分。它可以让游戏中的角色自动找到从一个位置到另一个位置的最佳路径。A搜索算法是一种常用的寻路算法,它可以在复杂的地图环境中快速找到最短路径。本文将详细介绍如何用A搜索算法实现游......
  • Java 冒泡排序 (Bubble Sort) ✨ 代码版 + Emoji讲解
    冒泡排序的基本思想就是让“大泡泡”不断往上浮,直到整个数组像泡泡浴一样排序好!......
  • 【含文档+PPT+源码】基于SpringCloud微服务的船舶交易平台的设计与实现
    项目背景与意义随着全球经济的快速发展,航运业成为国际贸易中不可或缺的一环。船舶交易平台作为航运业的重要组成部分,为船舶买卖、租赁等交易提供了便利和高效的途径。在传统的船舶交易中,买卖双方往往需要通过中介机构来进行交易,这不仅增加了交易的时间和成本,还存在信息不透明......
  • 算法实战:剖析 Redis 常用的数据类型对应的数据结构
    算法实战:剖析Redis常用的数据类型对应的数据结构Redis是一个非常流行的内存数据库,它提供了多种数据类型,每种数据类型都有其特定的数据结构支持。了解这些数据结构对于深入理解Redis的工作原理和优化使用非常重要。本文将剖析Redis常用的数据类型对应的数据结构,并通......
  • 网络编程-TCP
    网络通信基础1、网络通信的协议:TCP、UDP、IP2、网络通信模型:七层模型、四层模型3、网络通信理论:socket、IP、端口号、字节序4、网络IO模型:4种5、网络超时处理6、网络的广播、组播、单播网络通信的特征(局域网)不同设备在通信时,要求其IP地址必须处于同一网段网络通信协议......
  • AWVS漏洞扫描工具(扫描pikachu)
    1.首先进来输入扫描的网址ip2.来到这里啥也不改下一步3.选则全面新的报告4.开始扫描5.等它扫完就点击reports查看报告然后到处就欧克了......
  • javaweb基于SSH开发小型学生宿舍管理系统源码+报告 课程设计 大作业
    ......
  • 解决DHCP服务异常导致设备无法获取IP地址的方法
    DHCP在网络环境中会自动为网络中的设备分配IP地址和其他关键网络参数,可以简化网络配置过程。但是,如果DHCP服务出现异常时,设备可能无法正常获取IP地址,会影响到网络通信。本文讲述一些办法可以有效解决DHCP服务异常导致设备无法获取IP地址的问题。首先我们要先搞清楚DHCP服务......
  • VMware Tanzu Kubernetes Grid Integrated Edition 1.20 发布下载,新增功能概览
    VMwareTanzuKubernetesGridIntegratedEdition1.20发布下载,新增功能概览VMwareTanzuKubernetesGridIntegratedEdition(TKGI)1.20.0-运营商Kubernetes解决方案Kubernetes-basedcontainersolutionwithadvancednetworking,aprivatecontainerregistry,an......