您的位置:首页 > 其它

从jvm来看,scala中的@究竟是个什么鬼?@模式匹配符号(scala 词法分析 语法分析 常用)

2016-12-29 12:06 495 查看
从jvm来看,scala中的@究竟是个什么鬼?我也是初步尝试来看jvm的类文件,又是初次来分析@,如不对的地方,请各位指正!

先看一下@是个什么?

/**
*Createdbyadminon2016/12/29.
*/
objecttest7{
defmain(args:Array[String]){
valb=Some(2)
vala@Some(1)=Some(1)
println(b)
println(a)

valbb=2
valaa@"IMF"="IMF"
println(bb)
println(aa)

}
}


运行结果:

"C:\ProgramFiles\Java\jdk1.8.0_65\bin\java"-Didea.launcher.port=7541"-Didea.launcher.bin.path=.....com.intellij.rt.execution.application.AppMaintest7

Some(2)

Some(1)

2

IMF

Processfinishedwithexitcode0

 

但@在idea中源代码中点击不开,既不是函数,也不是运算符,那scala中编译后究竟是什么呢?能否从JVM来看看?

1,写2个scala文件,一个包含@,一个不包含@

TestNoOpera.scala不包含@

objectTestNoOpera{

 defmain(args:Array[String]){

  valb="IMF"

 }

}

TestInludeOpera.scala 包含@

objectTestInludeOpera{

 defmain(args:Array[String]){

  valaa@"IMF"="IMF"

 }

}

2,scalac编译成class文件.



3,从class类查看工具javaclassviewer分别看一下 TestInludeOpera$.class和 TestNoOpera$.class文件 

 3.1:TestNoOpera$.class文件 





说明:

opcode[12]-0000:ldc16[String:IMF] //ldc指令从运行时常量池中加载字符串常量“IMF”(常量池中16的位置,字符串索引为15,名称为IMF),并把IMF推入到JVM的操作数栈。

opcode[4D]-0002:astore_2//astore指令把IMF变量从操作数栈顶弹出,存入局部变量表。a意思是操作引用类型。

opcode[B1]-0003:return //什么也没有做,那就return指令返回,没有返回值。将结果返回给调用方。

3.2TestInludeOpera$.class 包含@操作符的类文件



opcode[12]-0000:ldc16[String:IMF]//ldc指令从运行时常量池中加载字符串常量“IMF”(常量池中16的位置,字符串索引为15,名称为IMF),并把IMF推入到JVM的操作数栈。

opcode[4E]-0002:astore_3  //astore指令把IMF变量从操作数栈顶弹出,存入局部变量表的字段3。

opcode[12]-0003:ldc16[String:IMF] //ldc指令从运行时常量池中加载字符串常量“IMF”,并把IMF推入到JVM的操作数栈。

opcode[2D]-0005:aload_3 //aload从局部变量表又取出了IMF变量,将IMF变量推入到操作数栈顶

opcode[3A]-0006:dstore4//dstore指令将变量IMF从操作数栈顶弹出,存到到局部变量表的字段4.

opcode[59]-0008:dup//dup复制操作数栈顶的变量IMF

opcode[C7]-0009:ifnonnull12//ifnonnull判断值是否为空

opcode[57]-0012:pop  //pop指令对操作数栈进行操作,将栈顶的变量IMF弹出 

opcode[19]-0013:aload4  //aload从局部变量表的字段4 取出了IMF变量,将IMF变量推入到操作数栈顶

opcode[C6]-0015:ifnull14 //ifnnull判断值是否为空

opcode[A7]-0018:goto19//无条件跳转到偏移量19的位置 

opcode[19]-0021:aload4//aload从局部变量表的字段4 取出了IMF变量,将IMF变量推入到操作数栈顶

opcode[B6]-0023:invokevirtual20[Methodref:java.lang.Object.equals,parameter=(java.lang.Object),returns=boolean]//invokevirtual指令从对象的类中查找要调用的方法,如果找不到方法,就报异常,这里是调用Object的equals方法,入参数是对象,返回值是布尔值

opcode[99]-0026:ifeq11//判定是否相等 

opcode[12]-0029:ldc16[String:IMF]// //ldc指令从运行时常量池中加载字符串常量“IMF”,并把IMF推入到JVM的操作数栈。

opcode[3A]-0031:dstore5///dstore指令将变量IMF从操作数栈顶弹出,存到到局部变量表的字段5

opcode[19]-0033:aload5// //aload从局部变量表取出了IMF变量,将IMF变量推入到操作数栈顶

opcode[4D]-0035:astore_2// //astore指令把IMF变量从操作数栈顶弹出,存入局部变量表的字段2。

opcode[B1]-0036:return//return返回

//以下是异常的处理

opcode[BB]-0037:name_new22[Class:scala.MatchError]//new指令的操作数是一个unit16的索引,这里是22,我们通过这个索引,从类的运行时常量池中找到类符号引用,解析这个类符合引号,那就可以拿到类数据,创建对象,并且将对象引用推入到操作数栈顶,new指令完成.

opcode[59]-0040:dup  //dup复制操作数栈顶的变量MatchError

opcode[2D]-0041:aload_3//aload从局部变量表取出了IMF变量,将IMF变量推入到操作数栈顶

opcode[B7]-0042:invokespecial25[Methodref:scala.MatchError.<init>,parameter=(java.lang.Object),returns=void]//invokespecial调用MatchError方法

opcode[BF]-0045:athrow//athrow是引用类指令,将MatchError异常对象引用从操作数栈顶弹出,并跳转到异常处理代码.



四:结论:

@符号在scala编译中做了一个模式配置的工作,将字符串做了比对,如果值相等,将将这个值取到赋值给变量;如果值不相等,匹配不上,就报一个异常.

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: