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

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

    先看一下@ 是个什么?

    object TestScala {
      def main(args: Array[String]): Unit = {
        val b = Some(2)
        val a@Some(1) = Some(1)
        println(b)
        println(a)
    
        val bb = 2
        val aa@"IMF" = "IMF"
        println(bb)
        println(aa)
    
      }
    }

    运行结果:

    Some(2)
    Some(1)
    2
    IMF

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

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

    TestNoOpera.scala 不包含@

    object TestNoOpera {
      def main(args: Array[String]) {
        val b="IMF"
      }
    }

    TestInludeOpera.scala  包含@

    object TestInludeOpera {
      def main(args: Array[String]) {
       val aa@"IMF" ="IMF"
      }
    }

    2,scalac 编译成class文件

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

     3.1:TestNoOpera$.class文件 

    说明:

    opcode [12] - 0000: ldc 16 [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: ldc 16 [String: IMF]//ldc指令从运行时常量池中加载字符串常量 “IMF” (常量池中16的位置,字符串索引为15,名称为IMF),并把IMF推入到JVM的操作数栈。
    opcode [4E] - 0002: astore_3  //astore指令把IMF变量从操作数栈顶弹出,存入局部变量表的字段3。
    opcode [12] - 0003: ldc 16 [String: IMF] //ldc指令从运行时常量池中加载字符串常量 “IMF” ,并把IMF推入到JVM的操作数栈。
    opcode [2D] - 0005: aload_3   //aload 从局部变量表又取出了 IMF变量,将IMF变量推入到操作数栈顶
    opcode [3A] - 0006: dstore 4 //dstore 指令将变量IMF从操作数栈顶弹出,存到到局部变量表的字段4 .
    opcode [59] - 0008: dup //dup复制操作数栈顶的变量IMF
    opcode [C7] - 0009: ifnonnull 12 //ifnonnull判断值是否为空
    opcode [57] - 0012: pop     // pop指令对操作数栈进行操作,将栈顶的变量IMF弹出 
    opcode [19] - 0013: aload 4  //aload 从局部变量表的字段4 取出了 IMF变量,将IMF变量推入到操作数栈顶
    opcode [C6] - 0015: ifnull 14 //ifnnull判断值是否为空
    opcode [A7] - 0018: goto 19 //无条件跳转到偏移量19的位置 
    opcode [19] - 0021: aload 4 //aload 从局部变量表的字段4 取出了 IMF变量,将IMF变量推入到操作数栈顶
    opcode [B6] - 0023: invokevirtual 20 [Methodref: java.lang.Object.equals, parameter = (java.lang.Object), returns = boolean ] //invokevirtual 指令从对象的类中查找要调用的方法,如果找不到方法,就报异常,这里是调用Object的equals方法,入参数是对象,返回值是布尔值
    opcode [99] - 0026: ifeq 11 //判定是否相等 
    opcode [12] - 0029: ldc 16 [String: IMF] // //ldc指令从运行时常量池中加载字符串常量 “IMF” ,并把IMF推入到JVM的操作数栈。
    opcode [3A] - 0031: dstore 5 ///dstore 指令将变量IMF从操作数栈顶弹出,存到到局部变量表的字段5
    opcode [19] - 0033: aload 5 // //aload 从局部变量表取出了 IMF变量,将IMF变量推入到操作数栈顶
    opcode [4D] - 0035: astore_2 // //astore指令把IMF变量从操作数栈顶弹出,存入局部变量表的字段2。
    opcode [B1] - 0036: return // return返回

    //以下是异常的处理
    opcode [BB] - 0037: name_new 22 [Class: scala.MatchError] //new指令的操作数是一个unit16的索引,这里是22,我们通过这个索引 ,从类的运行时常量池中找到类符号引用 ,解析这个类符合引号,那就可以拿到类数据,创建对象,并且将对象引用推入到操作数栈顶,new指令完成.
    opcode [59] - 0040: dup  //dup复制操作数栈顶的变量MatchError
    opcode [2D] - 0041: aload_3 //aload 从局部变量表取出了 IMF变量,将IMF变量推入到操作数栈顶
    opcode [B7] - 0042: invokespecial 25 [Methodref: scala.MatchError.<init>, parameter = (java.lang.Object), returns = void] //invokespecial 调用MatchError方法
    opcode [BF] - 0045: athrow //athrow是引用类指令,将MatchError异常对象引用从操作数栈顶弹出,并跳转到异常处理代码.

    四:结论:

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

  • 相关阅读:
    (4.3)ODBC/OLE DB/ADO概念与使用情况
    查找至少连续出现三次的所有数字/连续3天的日期【LeetCode】
    javascript 事件触发
    document.referrer
    创业公司
    关于javascript 回调函数
    promise
    javascript deferred
    document.readystate
    window---->load, document------DOMContentLoaded
  • 原文地址:https://www.cnblogs.com/itboys/p/9300605.html
Copyright © 2011-2022 走看看