当前位置:网站首页>反射(二)
反射(二)
2022-07-07 02:11:00 【Cold Snowflakes】
静态加载和动态加载
静态加载:编译时加载相关的类,如果没有找到则报错。
动态加载:运行时加载需要的类。
反射是动态加载,只有被执行到的时候,才会去加载类。
public class Main{
public static void main(String args[]) throws ClassNotFoundException{
// 静态加载, 编译的时候就要进行加载, 如果没找到就会报错, 依赖性很强
Cat cat = new Cat();
// 动态加载, 编译的时候不去管它, 也不会去检查 被加载的类是否存在
// 真正运行且执行到这段代码的时候才会去加载
Class.forName("com.itheima.Cat");
}
}
类加载
当程序要使用某个类时,如果该类还未被加载到内存,则系统会通过类的加载,类的连接,类的初始化这三个步骤来对类进行初始化。
一般情况下,JVM将会连续完成这三个步骤,所以有时也把这三个步骤统称为类加载。
类的加载:JVM将字节码从不同的数据源(class文件,jar包,网络等等)转化为二进制字节流加载到内存中,并生成Class实例对象。
类的连接
验证阶段:确保 .class 文件的字节流中包含信息符合当前虚拟机要求,不会危害虚拟机自身安全。
准备阶段:为static修饰的字段变量分配内存并且设置默认初始值,不包含用final修饰的static,因为final在编译的时候就会分配了。
解析阶段:主要将常量池中的符号引用替换为直接引用的过程。
类的初始化:类加载最后阶段,真正开始执行类中定义的Java程序代码,此阶段是执行 < clinit >()方法的过程。
< clinit >()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。
虚拟机会保证一个类的 < clinit >()方法在多线程环境中被正确地加锁,同步,如果多个线程同时去初始化一个类,则只会有一个线程去执行这个类的 < clinit >()方法,其他线程都需要阻塞等待,直到活动线程执行 < clinit >() 方法完毕。
若该类具有超类,则对其进行初始化,执行静态初始化器和静态初始化成员变量。
@SuppressWarnings({
"all"})
public class lambdademo {
public static void main(String[] args) {
System.out.println(fun.num);
}
}
/** * 在 Linking 的 Preparation 阶段, 对 num 分配内存,初始化为 0 * 在 Initialization 阶段, 收集 静态变量,静态代码块 至 <clinit> 方法中, 并执行 <clinit>方法 */
class fun {
static{
System.out.println("静态代码块被执行");
num = 300;
}
static int num = 100;
public fun(){
System.out.println("构造器被执行");
}
}
// Output
静态代码块被执行
100
// 分析结果, 可以明显地看到, 类加载中做了什么, 当然我们并没有去创建对象, 所以构造方法也没有被调用
// 大致的过程应该是这样
1. 加载 fun 类, 并生成对应的一份 Class实例, 以及在方法区中的 字节码二进制数据
2. Linking阶段, 为 num 分配内存,初始化为 0
3. Initialization阶段, 按在源文件中出现的顺序, 依次收集所有静态变量的赋值动作和静态代码块中的语句,合并至<clinit>方法中,并执行。
clinit() {
///静态代码块中的语句/
System.out.println("静态代码块被执行");
num = 300;
///静态变量赋值语句//
num = 100;
}
Field类的一些其他API
getModifiers(): default/0 , public/1 , private/2 , protected/4 , static/8 , final/16
// 可以使用 Modifier.toString(cls.getModifiers()) 将数字转为字符串
getType(): 返回一个 Class对象,表示属性的类型
getName(): 返回属性名
Class<fun> funClass = fun.class;
Field[] fields = funClass.getDeclaredFields();
for(Field f : fields){
System.out.println(f.getModifiers()); // 返回数值代表其访问权限修饰符
System.out.println(f.getType()); // int/double/java.lang.String ...
System.out.println(f.getName()); // 属性名
}
Mehod类
getModifiers() // 访问权限修饰符
getReturnType() // 返回Class对象,表示返回类型
getName() // 方法名
getParameterTypes() // 返回Class[], 表示参数类型数组
通过反射创建对象
Class<?> cls = Class.forName("com.itheima.fun");
// 1.使用无参构造器
Object o1 = cls.newInstance();
// 2.通过有参构造器(指定参数列表)
Constructor<?> cons1 = cls.getDeclaredConstructor(String.class);
Object o2 = cons1.newInstance("xxx");
// 3.也可以使用private的构造器
Constructor<?> cons2 = cls.getDeclaredConstructor(int.class, String.class);
cons2.setAccessible(true);
Object o3 = cons2.newInstance(100, "fang_shou_ba..");
Class对象的生成方式如下:
1、类名.class
JVM将使用类装载器, 将类装入内存,不做类的初始化工作,返回Class的对象。
2、Class.forName(“类的全限定名”)
装入类,并做类的初始化(会执行静态代码块和初始化静态变量),返回Class的对象。
平时使用 new 创建对象时,会先进行类加载,之后执行 非静态的代码块,之后执行构造函数。
几种生成Class实例方法的区别
边栏推荐
- Apache ab 压力测试
- MySQL卸载文档-Windows版
- [Shell]常用shell命令及测试判断语句总结
- ICML 2022 | explore the best architecture and training method of language model
- The difference between string constants and string objects when allocating memory
- Find duplicate email addresses
- 蚂蚁庄园安全头盔 7.8蚂蚁庄园答案
- Postgresql源码(59)分析事务ID分配、溢出判断方法
- How to find the literature of a foreign language journal?
- 安装VMmare时候提示hyper-v / device defender 侧通道安全性
猜你喜欢
Apache ab 压力测试
项目实战 五 拟合直线 获得中线
Pinduoduo lost the lawsuit: "bargain for free" infringed the right to know but did not constitute fraud, and was sentenced to pay 400 yuan
Laravel uses Tencent cloud cos5 full tutorial
Force deduction 62 different paths (the number of all paths from the upper left to the lower right of the matrix) (dynamic planning)
Programmers' daily | daily anecdotes
Markdown 并排显示图片
基于ADAU1452的DSP及DAC音频失真分析
dolphinscheduler3.x本地启动
【OpenCV】形态学滤波(2):开运算、形态学梯度、顶帽、黑帽
随机推荐
Open the blue screen after VMware installation
C语言面试 写一个函数查找两个字符串中的第一个公共字符串
uniapp开发小程序如何使用微信云托管或云函数进行云开发
Oracle迁移中关于大容量表使用数据泵(expdp、impdp)导出导入容易出现的问题和注意事项
ETCD数据库源码分析——从raftNode的start函数说起
计算模型 FPS
Crudini profile editing tool
程序员的日常 | 每日趣闻
mobx 知识点集合案例(快速入门)
FlexRay通信协议概述
LM小型可编程控制器软件(基于CoDeSys)笔记二十三:伺服电机运行(步进电机)相对坐标转换为绝对坐标
[SOC FPGA] peripheral PIO button lights up
Developers don't miss it! Oar hacker marathon phase III chain oar track registration opens
蚂蚁庄园安全头盔 7.8蚂蚁庄园答案
软件测试到了35岁,真的就干不动了吗?
Test the foundation of development, and teach you to prepare for a fully functional web platform environment
Crudini 配置文件编辑工具
postgresql 数据库 timescaledb 函数time_bucket_gapfill()报错解决及更换 license
3428. Put apples
Performance comparison between Ceres solver and g2o