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(“实参”)

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【媒体热点资讯】2013eoe移动开发者大会圆满落幕

    【媒体热点资讯】2013eoe移动开发者大会圆满落幕

    2021年8月26日
    75
  • java.util.ConcurrentModificationException

    java.util.ConcurrentModificationExceptionjava.util.ConcurrentModificationException

    2022年4月23日
    59
  • Pycharm2020.1安装中文语言插件教程,不需要汉化

    Pycharm2020.1安装中文语言插件教程,不需要汉化方法一(在搜索不到插件):1.安装好Pycharm并打开Pycharm2.打开File,找到Settings并打开3.打开Settings中的Pulgins,选择Marketplace,搜索chinese出现下图这个就可以在线安装,不出现离线安装(方法二)方法二(推荐):1.查看Pycharm版本help–about2.打开中文插件的下载地址(https://plugins.j…

    2022年5月9日
    305
  • 5g网络切片是什么意思_网络切片是5G网络的标志性

    5g网络切片是什么意思_网络切片是5G网络的标志性众所周知,5G网络除了高速度、低时延外,还将承载万物互联,而要满足各种不同垂直行业的差异化需求,就要依靠5G网络切片来实现。因此有专业人士认为网络切片是5G的核心,是运营商服务垂直行业的基础和关键。那么,到底什么是网络切片,为什么5G需要网络切片?网络切片,到底“切”的是什么?01切片技术是5G网络的核心2020年以来,5G建设浪潮奔涌而来,行业应用加速落地,5G与产业加速渗透融合,与经济高质量发展、社会数字化转型的联系愈发紧密。“4G改变生活,5G改变社会”,虽然当前5G的建设成果及其展现出的威

    2022年9月28日
    4
  • linux大量kworker_linux load average 非常高

    linux大量kworker_linux load average 非常高aarch32linux4.14最近遇到一个kworker问题,callstack如下,线程adas的陷入kernelspace后会schedule_work调用一个while(1)的worker,killadas后重新启动adas后adas线程会在调用dma_alloc_coherent的时候block住以前的经验一直kworker为轻量的线程和可睡眠的中断下半部,对kwor…

    2022年9月25日
    3
  • java 文件转inputstream_把文本转换成表格

    java 文件转inputstream_把文本转换成表格以下是一些将InputStream转换为FileJava示例手动将InputStream复制到FileOutputStreamApacheCommonsIO–FileUtils.copyInputStreamToFileJava1.7NIOFiles.copy1.FileOutputStream1.1我们必须将数据从InputStream手动复…

    2022年9月21日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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