服务器方法无法接收前端参数_面向JVM编译-while、if-else以及方法参数的接收

码神手记-资深攻城狮的私房笔记,微信公众平台/知乎/头条同步,动动小手,点个关注!

5055812fc4e1fe418f382e84c1076596.png

在面向JVM的编译(一)-常量、局部变量以及控制结构的使用 中,介绍过for循环的编译,今天再补充一些其它的控制结构(while循环与if-else)以及方法参数的接收。本篇内容同样需要你先了解JVM运行时数据区域的基础知识。

while循环与if-else

Java代码:

void whileInt() {    int i=0;    while (i < 100) {        i++;    }}

JVM代码:

Method void whileInt()0    iconst_0        //把整型常量0压入操作数栈1    istore_1        //从操作数栈中弹出0并存为局部变量12    goto 8          //强制转移控制到指令数组中索引为8的指令5    iinc 1 1        //局部变量1的值加18    iload_1         //将局部变量1的值(0)压入操作数栈9    bipush 100      //将整数100压入操作数栈11   if_icmplt 5     //比较栈顶两个数的大小,如果i<100,控制转移到索引为5的指令。否则继续执行下一条指令14   return          //返回Void

与之前for循环的例子是同样的情况,在以上JVM代码中,判断两数大小的指令(if_icmplt)位于JVM代码的底部。使用goto指令强制转移控制,以便在第一次迭代之前先执行判断(或者叫test)。其它的控制结构也是以类似的方式被编译,但需要注意:指令与数据类型要匹配。

将上面例子中的数据类型换为double:

void whileDouble() {    double i=0.0;    while (i < 100.1) {        i++;    }}

编译后的JVM代码如下:

Method void whileDouble()0    dconst_0        //把double类型常量0压入操作数栈1    dstore_1        //从操作数栈中弹出0并存入局部变量12    goto 9          //控制转移到索引为9的指令5    dload_1         //将局部变量1压入操作数栈6    dconst_1        //把double类型常量1压入操作数栈7    dadd            //弹出栈顶的两个double值,相加结果压入操作数栈8    dstore_1        //弹出相加结果存为局部变量1(原来的局部变量1被覆盖)9    dload_1         //将局部变量1压如操作数栈,i的当前值10   ldc2_w #4       //从运行时常量池中加载索引为4的double值,即100.113   dcmpg           //比较栈顶两个double值的大小,即比较i的当前值与100.1的大小。14   iflt 5          //如果i<100.1,则控制转移到索引为5的指令,否则继续执行后续指令17   return          //返回Void

每个浮点数据类型都有两个比较指令:fcmpl和fcmpg用于float类型,dcmpl和dcmpg用于double类型,这些指令针对NaN会特殊处理。NaN是无序的,只要在操作数中有一个NaN,浮点比较的结果就会是失败(False)。在数据类型章节中有提到过NaN,NaN属于浮点类型,是浮点值集的一员,代表某些无效操作比如0.0/0.0,注意这里的0是浮点类型。

关于dcmpg指令做一些补充,如果操作数存在NaN或者不满足比较条件,将会向操作数栈压入整数1,如果两个操作数相等则压入0,如果满足比较条件则压入-1。iflt指令判断的是1,0,-1,另外还有ifge、ifle指令,和iflt同理。

方法参数的接收

实例方法

当一个实例方法被调用时,会在栈中创建一个新的栈帧(即当前栈帧)。如果该方法有n个参数,那么这n个参数将会按照顺序存入当前栈帧局部变量表索引1到n的位置。

示例:

int addTwo(int i,int j){    return i+j;}

编译后:

Method int addTwo(int,int)0    iload_1        //将局部变量1(i)压入操作数栈1    iload_2        //将局部变量2(j)压入操作数栈2    iadd           //从操作数栈弹出i和j,执行相加操作,将int类型的结果压入操作数栈3    ireturn        //从操作数栈弹出计算结果,返回一个int数值

上文提到方法的参数被存入局部变量表索引1到n的位置,那么索引为0的位置存储的是什么?按照约定,索引为0的位置存储的是一个引用,指向的是被调用实例方法所属的对象实例。在Java编程语言中,可以通过this关键字访问到这个对象实例。

类方法

类(static)方法没有实例,因此参数会从索引0开始存入局部变量表。

示例:

static int addTwoStatic(int i,int j){    return i+j;}

编译后:

Method int addTwoStatic(int,int)0    iload_0        //将局部变量0(i)压入操作数栈1    iload_1        //将局部变量2(j)压入操作数栈2    iadd           //从操作数栈弹出i和j,执行相加操作,将int类型的结果压入操作数栈3    ireturn        //从操作数栈弹出计算结果,返回一个int数值

从例子中可以明显看出类方法与实例方法在参数接收上的区别,类方法的参数直接从局部变量表的索引0开始存储。

码神手记-资深攻城狮的私房笔记,微信公众平台/知乎/头条同步,动动小手,点个关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值