Day350&351&352(1)

1、复习:再谈操作数栈与局部变量表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-41hgTFk6-1628176007568)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210804215838094.png)]

在这里插入图片描述

i/s是槽位共用,因为int i = 0出了代码块,就失效了,所以下面的String s变量就不开辟新的槽位,直接复用上面的i


2、局部变量压栈指令

Xload操作从局部变量表中的指定索引位置的变量,压入操作数栈中

在这里插入图片描述

在这里插入图片描述


3、常量入栈指令

const、push、ldc将常量压入操作数栈

对应的常量表示数值的范围依次变大

在这里插入图片描述在这里插入图片描述

在这里插入图片描述


4、出栈入局部变量表指令

在这里插入图片描述

里面有代码,也有字节码,所以可以根据老师给的图展开分析,首先该方法被调用的时候,形式参数k和d都是有确定的值,由于该方法不是静态方法,所以局部变量表中的第一个位置(槽位)存储this,而第二个位置存储k具体的值,由于老师只是分析,没有调用这个方法,所以老师全部使用的变量名称来代替具体的值,所以明白就好,继续来分析,然后第三个和第四个位置储存d具体的值,由于d是double类型,所以需要占据两个槽位,数据已经准备好了,那就来看字节码,首先iload_1是将局部变量表中下标为1的k值取出来压入操作数栈中,然后iconst_2是将常量池中的整型值2压入操作数栈,iadd让操作数栈弹出的k值和整型值2执行相加操作,之后将相加的结果值m压入操作数栈中,请注意老师的画法,在执行弹栈和压栈操作之后,老师并没有删除操作数栈中的k值和2,这是因为老师让我们知道具体的操作过程,所以故意为之,不过真正的操作是弹栈之后k值和2就会从操作数栈中弹出,之后操作数栈中就没有k值和2了,只有m值了,然后istore_4是将操作数栈中的m值弹出栈,然后存在局部变量表中下标为4的位置,idc2_w #13代表将long型值12压入操作数栈,istore5是将值12弹栈之后放入局部变量表中下标为5的位置,由于12是long型,所以占据两个位置(槽位),ldc #15代表将字符串atguigu压入操作数栈,astore 7代表将字符串atguigu弹栈之后放入局部变量表中下标为7的位置,idc #16代表将float类型数据10.0压入操作数栈,fstore 8代表将10.0弹出栈,然后放入局部变量表中下标为8的位置,idc2_w #17代表将10.0压入操作数栈,dstore2代表将10.0弹出栈,之后将10.0放入下标为2和3的操作,毕竟这是double类型数据


槽位复用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MdXqYGfj-1628176007586)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210805215434297.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WFVt56o1-1628176007587)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210804220138314.png)]

注意在方法没有运行的时候,根据字节码文件就可以计算出需要几个槽位


三、算数指令


在这里插入图片描述


对于无穷大和NaN的举例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uIXHieHM-1628176007591)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210805215554254.png)]


1、所有算术指令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0kStJowm-1628176007592)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210805215652976.png)]


①举例

在这里插入图片描述


②一个曾经的案例1

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D6kgrwVz-1628176007597)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210805215807100.png)]


2、比较指令的说明

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3l3n4vlq-1628176007598)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20210805215921128.png)]

注意:NaN(Not a Number)表示不是一个数字,比如0.0/0.0得到的可能是1.0(两个数相等),也可能是0.0(0.0是分子),也可能是无穷大(0.0是分母),所以老师给出的解释是NaN代表无法确定是什么数字,只有double和float类型中可能出现NaN的情况,而long类型不会出现NaN,所以只有lcmp,而没有lcml


3、i++和++i的区别

在这里插入图片描述

  • 对于i++,先赋值后++

先加载10到操作数栈【bipush 10】,并保存到局部变量表1索引的位置(0的位置是this)【istore_1】,然后自增局部变量表索引1的变量【iinc 1 by 1】,(此时10还在操作数栈中),然后把操作数栈中当前的10,存储在索引2中【istore_2】,最终的结果是i=11(索引1的位置),a=10(索引2的位置);总结i=11,a=10;

  • 对于++i,先++后赋值

先是加载20到操作数栈中【bipush 20】,将操作数栈20的数据保存到索引3的位置【istore_3】,自增索引3位置的数据【iinc 3 by 1】,此时索引3的数据是21,加载索引3的数据到操作数栈中【iload_3】,然后存储到索引为4的位置,此时索引为3的数据为21,索引为4的数据也是21,;总结j=21,b=21;

对于++i和i++,对于i都会自增,但是对于他所赋值给的对象,会有不同的时机进行自增;


四、类型转换指令


针对java中的基本类型

image-20210806210321958

1、宽化类型转换

容量小的转换为大的,自动类型提升

image-20210806210851895

image-20210806211814662


2、窄化类型转换

容量大的转化为小的,强制类型转换

image-20210806211954918

注意从float、double、long等类型往byte、short、char类型转换的时候,需要先把前面几种类型转换成int类型,然后在从int类型转换到后面这几种类型,所以int类型相等于一种过渡类型

image-20210806213319995


五、对象的创建与访问指令


面向对象包含:类类型、数组类型

image-20210806205821371

1、创建指令

image-20210806213540773

image-20210806214319224

image-20210806214613883


2、字段访问指令

image-20210806214721913


image-20210806214857934

注意:get是入栈,而put是出栈

image-20210806220412613


3、数组操作指令

image-20210806205946182

image-20210806205954131

image-20210806223333072


4、类型检查指令

image-20210806210014795

image-20210806224047903


六、方法调用与返回指令


1、方法调用指令

image-20210807135837066

  • invokespecial:↓静态分派

image-20210807140449703


  • invokestatic:↓

image-20210807140623342


  • invokeinterface:↓

image-20210807140900288


注意

1、invokedynamic老师不讲,估计是很少遇到吧

2、invokeinterface是对接口而言的,用属于接口类型的对象调用方法的时候就是这个

3、invokespecial只有构造器、私有方法、super.方法名()调用父类方法这几种情况,其中调用父类方法这种情况可能出现其直接父类没有该方法,那就可以调用其父类继承的父类中的该方法,最终找到一个方法调用就是了

4、invokestatic是调用static静态方法,无论是使用对象.静态方法名()还是类名.静态方法名()都是invokestatic,也不难理解

5、invokevirtual是调用类中的非静态普通方法,而这种实例方法可能调用的是子类重写的非静态普通方法,比如A a = new B();a.hello(),其中B类继承A类,并且B类重写了A类中的hello()方法,这种情况下就是invokevirtual了,但是有可能该类没有子类,调用的就是本类中的非静态普通方法,这种情况也是invokevirtual了


2、方法返回指令

image-20210807142108572


image-20210806210141297


七、操作数栈管理指令


image-20210807142243600

image-20210807144353007

image-20210807143614309


八、控制转义指令


image-20210807143723137

1、条件跳转指令

image-20210807145110709

image-20210807143752490

image-20210807150621663

注意

1、对于float、double、long类型的比较,它们比较之后生成的是int类型的0、1、-1,这个过程可以使用比较指令和条件跳转指令来完成,虽然得到的是int类型的值,但是System.out.println(XXX)中的值是布尔类型,你可以在jclasslib中的常量池信息中看到写的是Z,代表布尔值类型

2、int类型值(包含byte、char、short)比较 和 对象类型值比较需要使用比较条件跳转指令


2、比较条件跳转指令

image-20210807151513209

注意

1、上面所说的后者是栈顶元素,而前者是栈顶下面的元素

2、对于float、double、long类型的比较,它们比较之后生成的是int类型的0、1、-1,这个过程可以使用比较指令和条件跳转指令来完成

而 int类型值(包含byte、char、short)比较 和 对象类型值比较需要使用比较条件跳转指令,其中对象类型值不是比较的地址,就是比较对象中的某些字段值,这又归咎到float、double、long、int类型的比较中了

3、无论哪种比较,也不管两个比较值的中间是什么符号(>、=、


3、多条件分支跳转

image-20210807152556122

image-20210807143906456

image-20210807153218341


  • tableswitch:↓

image-20210807152900135


  • lookupswitch:↓

image-20210807153257314

  • jdk7加入判断String类型的方式:↓

通过计算这个String字符串的hash值来判断是否相等

image-20210807153741704

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值