今日总结
jvm 黑马 108-139p
JVM
2 字节码指令
javap -v xxx.class
字节码执行流程
main方法类加载,放在方法区,常量池(class数据)放入运行时常量池
小的数字放在放的方法的字节码指令,超过范围放在常量池
- x=x++为什么没用
因为先把x放到操作数栈,然后x++,最后又将操作数栈的值给x,这时候还是0。
i++是先load再自增,++i是先自增再load
- cinit
编译器按按从上至下的顺序, 将所有的静态代码块和静态成员赋值的代码,合并成一个特殊的方法,()V
- init
实例对象。
init方法,也是按顺序,构造方法最后执行
- 方法调用
构造方法:invokespecial
私有:invokespecial
final:invokespecial
public:invokevirtual(因为有可能重写)
接口方法:invokeInterface(支持多态)
静态方法:invokestatic
new 方法:堆中给对象分配内存—分配成功之后把对象的引用放入操作数栈—将栈顶的元素复制一份—invokespecial执行栈顶元素的构造方法并移除—把剩下的一个出栈存到局部变量表中
不要通过对象调用静态方法、变量,会产生两条没用的虚拟机指令
- 多态的原理
虚方法表在链接阶段就会生成,就生成了虚方法表的入口地址
- 通过栈桢中国的对象引用找到对象、
- 分析对象头,找到对象的实际classsss
- class结构中有vtable,在类加载阶段已经根据方法重写规则生成好了
- 查表得到方法的具体地址
- 执行方法的字节码
- 异常的处理
有一个Exception table,监测try代码,出现异常之后进行类型匹配,看是否一致或者是子类异常。
多个catch:异常表里面有多个 。因为只会有一个异常,所以局部变量表只占一个槽位(节省了栈桢的内存)
multi-catch:出现了多个异常。xxx E | xxxE | xxxE:三个不同类型的异常入口是一样的。
- finally
将finally的代码既放到了try块又放到了catch块
除了try和catch中无法捕获的,都会跳到最后,类型是any,去执行,当然这里面也复制了finally的东西
20。
try里面放了finally的代码,最终肯定要执行。
所以千万不要在finally中写return,因为可能会异常被吞
10
没有return语句,会有一个slot来暂存,而且也会throw异常
- synchronized
如何成对加锁解锁?
先a_load把lock对象加载到操作数栈,表示synchronized开始
然后把引用复制一份放进来存入槽位,给monitorenter和monitorexit来用 (两个会消耗lock引用)
monitorenter 开始lock引用
加载之前的lock,执行monitorexit解锁,异常也一样,都会加载lock对象的引用,进行解锁。
3 编译期处理
编译期间的优化和处理:语法糖 (编译过程自动生成和转换一些代码)
- 默认构造器
会生成默认的构造器(没有自己写的情况下),因为所有的都继承自Object。
- 自动拆装箱
int->Integer:装箱
Integer->int:拆箱
- 泛型集合取值
范型擦除: 编译之后统一设置成Object
返回的时候返回的是Object:用checkcast,将object变成Integer(相当于自动做了一次强制类型转换)
方法体内的信息被擦除了, 局部变量的范型没有被擦除,但是不能通过反射获得,只有在方法的参数和返回值上能通过反射获得
- 可变参数
String …args -> String[] args
如果不传参数,传的是一个空的String数组,而不是null值
- foreach
数组赋值可以直接int arr[] = {},会变成 int arr[] = new int[]{}
数组foreach 其实就是变成fori
list的foreach是使用的迭代器(实现了Iterator的都可以用)
- switch 字符串
实际上比较的hash code
- 为什么既比较hashcode,又利用equals比较呢?
hashcode是为了提高效率,减少比较,equals是为了比较hash冲突,
因为大多的hashcode都是唯一的。
- 为什么要重写hashcode和equals?
- 用于只需要比较一个值的情况,比如不同的对象,id一样就可以认为是同一个
equals相等,hashcode必定相等,hashcode用于快速比较,equals用于绝对相等。hashcode存在冲突情况,所以要进一步用equals比较
- 为什么重写equals必须重新给i额hashcode
- 如果两个对象相等,则 hashcode ⼀定也是相同的
- 两个对象相等,对两个 equals() ⽅法返回 true
- 两个对象有相同的 hashcode 值,它们也不⼀定是相等的
- 综上, equals() ⽅法被覆盖过,则 hashCode() ⽅法也必须被覆盖这部分借鉴于:https://juejin.cn/post/7025465769307668516,
- switch 枚举
ordinal()
- 枚举
本质是一个class,值实际上都是实例对象
是一个final的不能被继承 ,继承了枚举父类(支持范型)
构造方法私有
$values把枚举对象放入数组
今日复盘
早上睡了个大懒觉,下午打了会儿球,还是懈怠了。
leetcode做起来啊,代码写起来,项目部署搞起来。
明天还要看看面试题。