java反射

java反射

0、java在计算机的三个阶段

<span>java反射</span>

一、反射

1、反射快速入门

public class Test1 {
    public static void main(String[] args) {
        //加载资源文件
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("D:\\IDEA\\maven_code\\mavenProject\\ReflectionTest\\src\\person.properties"));
            //获取类的路径
            String classpath = properties.get("classpath").toString();
            //获取类的方法
            String method = properties.get("method").toString();
            //测试
            System.out.println(classpath);
            //通过反射创建person类的Class对象
            Class aClass = Class.forName(classpath);
            //通过aClass对象实例化Person
            Object o1 = aClass.newInstance();
            Object o2 = aClass.newInstance();
            System.out.println("实例化的类是否相等" + o1.equals(o2));
            //通过aClass对象获取方法
            Method method1 = aClass.getMethod(method);
            //调用方法-》 方法.invoke(类名)
            method1.invoke(o1);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

<span>java反射</span>

2、反射优缺点

优点:

​ 增加程序的灵活性,避免将程序写死到代码里

​ 代码简洁,提高代码的复用率,外部调用方便

​ 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法

缺点;

​ 1、性能问题

​ 使用反射基本上是一种解释执行,用于字段和方法接入时要远于直接代码。因此Java反射机制主要应用在对灵活性和扩展性要求 很高的系统框架上,普通程序不建议使用。

​ 反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作得多。我们应该避免 在经常被执行的代码或对性能要求很高的程序中使用反射。
​ 2、安全限制

​ 3、内部暴露

2.1、反射优化

在反射调用方法时,取消访问检查(可提升一点速度)

//方法.setAccessible(ture)
//true为取消检查

2.2、解释执行与编译执行

解释执行描述的是将源语言直接作为输入,每次执行一条就将源代码解释成机器码,并不保留中间结果。因为每次都需要解释所以移植性和跨平台性很高。

编译执行描述的是将源代码事先编译成目标机器的机器码文件,这样一来就直接可以在目标机器上运行,但是由于目标机器的不同,每次更换目标都需要重新编译与之相对的机器码文件,所以移植性较差。

3、Class类

3.1 基本介绍

  • Class也是一个类,因此继承Object类
  • Class类对象不是new出的,是Java虚拟机就会自动产生一个Class对象。
  • 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  • 每个类的实例知道自己由那个Class所生成
  • 通过Class对象的API可以完整的获得一个类的结构
  • Class对象是存在堆中
  • 类的字节码二进制数据,放在方法区中(称为类的元数据,包括方法代码,变量名,方法名,访问权限等)

3.2 常用方法

方法 作用
getName() 以 String 的形式返回此 Class 对象所表示的实体
aClass.getPackage().getName() 返回包名
aClass.getName() 返回全类名
newInstance() 产生其对应类的实例,它调用的是此类的默认构造方法
getField(“。。”) 获取属性
getFields() 获取所有属性

3.3 获取Class对象的方式

1.Class.forName();

​ 读取配置文件时常用(编译阶段)

2.类名.class

​ 用于参数传递(加载阶段)

3.对象.getClass()

​ 有对象实例时(运行阶段)

4.对象.getClass().getClasLoader().loadClass(“..”)

​ 类加载器获取

5.基本数据类型.class / .TYPE

​ int.class/int.TYPE

3.4 那些数据类型有Class对象

外部类,接口,数组,二维数组,注解,枚举,基本类型,void,class

4、类加载

1.基本说明

  • 静态加载:编译时加载相关类,如果没有则报错,依赖性太强
    • 创建对象时
    • 子类被加载,父类也加载
    • 调用类中的静态成员时
  • 动态加载:运行时加载需要的类,如果运行时没用到,则不会报错,降低依赖性(反射使用动态加载
    • 反射

2 类加载过程

类从被加载到虚拟机内存开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。其中验证、准备、解析三个阶段称之为连接。

<span>java反射</span>

加载:获取定义此类的二进制字节流。

​ 将这个字节流所代表的静态存储结构转换为方法区的运行时数据结构

​ 在内存中共生成一个代表这个类的java.lang.Class对象

验证:为了确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会威胁虚拟机自身的安全。其实如果纯粹是从Java源码编译得到的Class文件,自身是可以确保安全的,但是因为Class文件可以由任何途径产生(甚至可以由十六进制编辑器直接编写来产生Class文件),所以虚拟机很有必要对输入的字节流进行验证以维护自身的安全。
验证阶段需要完成四个阶段的校验动作:文件格式验证(基于二进制字节流)、元数据验证(基于方法区的存储结构)、字节码验证(基于方法区的存储结构)、符号引用验证()。也可以关闭安全验证

准备:对静态变量默认初始化,并分配空间(这里的初始值不是代码中指的初始值而是变量数据类型对应的零值(int为0,String为null等)。

解析:把符号引用转为直接引用

初始化:真正开始执行类中定义的Java程序代码,执行静态变量的初始化赋值

			此阶段执行**<clinit>()方法**的过程:按照编译器**语句**在源文件出现的**顺序**,依次收集类中的所有**静态变量的赋值**和**静态代码块**中的语句,并进行**合并**(在多线程环境中被正确的**加锁、同步**)

​ (因为有加锁的机制,才保证了类在内存中只有一份Class对象

5、获取类结构信息

1 .java.lang.Class类

<span>java反射</span>

2.java.lang.Field

Field.getModifiers()

修饰符的值:

默认 0

public 1

private 2

protected 4

static 8

final 16

组合 相加

3.java.lang.Method/java.lang.Constructor

getReturnType():得到方法返回值的class类型

getParameterTypes():形参数组情况

6、通过反射创建对象

暴破:使用反射可以访问private构造器

setAccessible(true)

1、默认无参构造一个对象

class.newInstance()

2、使用public构造器构造对象,

先获取构造器(getConstructors()),再constructor.newInstance(“实参”)

3、使用private构造器获取对象

先获取构造器(getDeclaredConstructors()),再使用暴破(constructor.setAccessible(true)),最后constructor.newInstance(“实参”)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115181.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • CSS导航条制作心得

    CSS导航条制作心得今天学习了导航条的制作,感觉收获很大!学习了一段时间的css和html。之前都是在慕课网上面看视频学习的,感觉收获不是特别大,有一点慢,效率不高。学东西还是得边做边学变想,学习编程最好能够不断地实践,毕竟实践出真知。学习了这个作者的文章http://www.missyuan.com/thread-438839-1-1.html    1.导航条放于div容器中——-ui和li来写

  • a算法解决八数码实验报告_人工智能常用算法模型

    a算法解决八数码实验报告_人工智能常用算法模型实验一A*算法求解8数码问题一、实验目的熟悉和掌握启发式搜索的定义、估价函数和算法过程,并利用A*算法求解N数码难题,理解求解流程和搜索顺序。二、实验原理A*算法是一种启发式图搜索算法,其特点在于对估价函数的定义上。对于一般的启发式图搜索,总是选择估价函数f值最小的节点作为扩展节点。因此,f是根据需要找到一条最小代价路径的观点来估算节点的,所以,可考虑每个节点n的估价函数值为两个分量:从起始节点到节点n的实际代价g(n)以及从节点n到达目标节点的估价代价h(n),且hn≤h*n,h*n

    2022年10月31日
  • Vue生命周期函数执行顺序_生命周期函数

    Vue生命周期函数执行顺序_生命周期函数createdcreated在刚进入页面的时候,会触发该函数的方法。只在页面刚开始加载时执行一次。activated一进入页面就触发;可用于初始化页面数据等

  • JedisCluster密码设置「建议收藏」

    JedisCluster密码设置「建议收藏」问题:通过jedisCluster.auth(”password”);报错:redis.clients.jedis.exceptions.JedisDataException:NOAUTHAuthenticationrequired如果是jedis单机模式的话,我们可以直接使用jedis.auth来进行设置Jedisjedis=newJedis(“127.0.0.1”,6379);jedis.auth(“password”);但是jedisCluster.auth(”p..

    2022年10月14日
  • StringBuilder 拼接「建议收藏」

    StringBuilder 拼接「建议收藏」packagecom.company;publicclassdemo{publicstaticvoidmain(String[]args){//创建一个StringBuilder对象,用来存储字符串StringBuilderhobby=newStringBuilder(“爱慕课”);StringB…

  • Android HandlerThread 详解

    Android HandlerThread 详解概述HandlerThread相信大家都比较熟悉了,从名字上看是一个带有Handler消息循环机制的一个线程,比一般的线程多了消息循环的机制,可以说是Handler+Thread的结合

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号