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

先看一下@ 是个什么?

  1. object TestScala {
  2. def main(args: Array[String]): Unit = {
  3. val b = Some()
  4. val a@Some() = Some()
  5. println(b)
  6. println(a)
  7.  
  8. val bb =
  9. val aa@"IMF" = "IMF"
  10. println(bb)
  11. println(aa)
  12.  
  13. }
  14. }

运行结果:

  1. Some()
  2. Some()
  3.  
  4. IMF

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

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

TestNoOpera.scala 不包含@

  1. object TestNoOpera {
  2. def main(args: Array[String]) {
  3. val b="IMF"
  4. }
  5. }

TestInludeOpera.scala  包含@

  1. object TestInludeOpera {
  2. def main(args: Array[String]) {
  3. val aa@"IMF" ="IMF"
  4. }
  5. }

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编译中做了一个模式配置的工作,将字符串做了比对,如果值相等,将将这个值取到赋值给变量;如果值不相等,匹配不上,就报一个异常.

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

  1. Akka系列(五):Java和Scala中的Future

    前言....... 随着CPU的核数的增加,异步编程模型在并发领域中的得到了越来越多的应用,由于Scala是一门函数式语言,天然的支持异步编程模型,今天主要来看一下Java和Scala中的Futrue ...

  2. Scala学习(五)---Scala中的类

    Scala中的类 摘要: 在本篇中,你将会学习如何用Scala实现类.如果你了解Java或C++中的类,你不会觉得这有多难,并且你会很享受Scala更加精简的表示法带来的便利.本篇的要点包括: 1. ...

  3. Programming In Scala笔记-第十一章、Scala中的类继承关系

    本章主要从整体层面了解Scala中的类层级关系. 一.Scala的类层级 在Java中Object类是所有类的最终父类,其他所有类都直接或间接的继承了Object类.在Scala中所有类的最终父类为A ...

  4. 第85讲:Scala中For表达式的强大表现力实战

    今天来学一下scala中的For表达式的用法. package scala.learn case class Persons(name:String,isMale:Boolean,children:P ...

  5. Scala中的函数

    Scala中的函数 提纲 1.Scala中的函数简介 2.Scala中的函数的各种写法 1.Scala中的函数简介 =================== Scala是函数式编程和面向对象式编程的混合 ...

  6. Scala中的流程控制

    一.分支控制if-else //Scala中if-else语句中,代码块内最后一句代码就是返回值 def main(args: Array[String]): Unit = { var age:Int ...

  7. scala学习手记4 - Java基本类型对应的scala类

    在Java中变量类型分为两大类:基本类型和引用类型.虽然在JDK1.5以后引入了自动装箱和自动拆箱机制,大大减少了我们在直接类型和引用类型之间的纠结,但仍有一些我们不得不考虑的问题.比如我在工作遇到的 ...

  8. [转] Scala 中的异步事件处理

    在任何并发性应用程序中,异步事件处理都至关重要.无论事件的来源是什么(不同的计算任务.I/O 操作或与外部系统的交互),您的代码都必须跟踪事件,协调为响应它们而执行的操作.应用程序可以采用两种基本方法 ...

  9. 第52讲:Scala中路径依赖代码实战详解

    今天学习了scala中的路径依赖,来看一下实战代码 class Outer{  private val x = 10  class Inner{    private val y = x +10  } ...

随机推荐

  1. PHP 二叉树 二叉排序树实现

    <?php /** * PHP 二叉树 * @author : xiaojiang 2014-01-01 * */ class Tree { protected $k = null; prote ...

  2. 【Java知识点专项练习】之 接口和抽象类的区别

    接口和抽象类的区别 接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的.接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为publi ...

  3. Puppet部署

    一.域名,IP规划  域名:beyond.com puppet master:puppet.sa.beyond.com 192.168.254.254 puppet client:  *.beyond ...

  4. 【大数据系列】HDFS初识

    一.HDFS介绍 HDFS为了做到可靠性(reliability)创建了多分数据块(data blocks)的复制(replicas),并将它们放置在服务集群的计算节点中(compute nodes) ...

  5. gradle-4.1-all.zip

    1. https://services.gradle.org/distributions/ https://services.gradle.org/distributions/gradle-4.1-a ...

  6. Linux 安装GCC讲解(在线和无网离线)

    本文主要介绍如何在无网络的环境下怎么离线安装GCC,如果有网,只需要通过命令 yum install gcc 进行安装就可以了,yum会自动把所有关联的依赖包也一起安装了,一键安装. yum inst ...

  7. URI Scheme注册伪协议实现远程命令执行

    Windows配置注册表注册伪协议 1.新建伪协议项 WIN+R 输入regedit 打开注册表,在注册表HKEY_CLASSES_ROOT键中新建一个项,项的名字就是你伪协议的名字,例如我注册一个c ...

  8. vscode 使用sublime风格代码

    Monokai 主题 One Dark Pro主题   vscode设置字体 "editor.fontFamily": "MONACO, Consolas, 'Couri ...

  9. Android按钮事件的4种写法

    经过前两篇blog的铺垫,我们今天热身一下,做个简单的例子. 目录结构还是引用上篇blog的截图. 具体实现代码: public class MainActivity extends Activity ...

  10. FPGA时序约束的几种方法 (转)

    FPGA时序约束的几种方法 对自己的设计的实现方式越了解,对自己的设计的时序要求越了解,对目标器件的资源分布和结构越了解,对EDA工具执行约束的效果越了解,那么对设计的时序约束目标就会越清晰,相应地, ...