scala关键字val、var、def的区别

最近做项目时碰到scala一个很难理解的问题,一个接口里定义了某个方法,实现类里什么实现代码都没有,就是声明了一个同名的变量就可以直接运行了,真是莫名其妙(说实话不喜欢Scala,太多例外了)。案例代码如下:

接口A:

trait A {
   def dataMap: Map[String, String]
}

实现类B:

class B extends A {
   val dataMap = Map[String,String]()
}
然后在B类中就可以直接使用接口A的dataMap方法了。明明都没有实现dataMap方法,怎么就可以直接使用这个方法了?


在回答上面的问题之前,先看下面的例子:

/**
  * Description: To Test the keyword of val,var,def.
  *
  * Author : Adore Chen
  * Created: 2018-01-23
  */
class Test {

  val f1: Int = { println("val"); 1 }

  var f2: Int = { println("var"); 2}

  def f3: Int = { println("def"); 3}

  def main(args: Array[String]): Unit = {

    val f4: Int = 1

    var f5: Int = 2

    println(f4)

  }

}
上面的测试类,使用val,var,def 并对他们不同位置进行了测试。我们使用 scalac Test.scala编译成Test.class,然后使用javap反编译查看具体实现:

javap -p -c Test
反编译的代码如下:

Compiled from "Test.scala"
public class Test {
  private final int f1;

  private int f2;

  public int f1();
    Code:
       0: aload_0
       1: getfield      #14                 // Field f1:I
       4: ireturn

  public int f2();
    Code:
       0: aload_0
       1: getfield      #18                 // Field f2:I
       4: ireturn

  public void f2_$eq(int);
    Code:
       0: aload_0
       1: iload_1
       2: putfield      #18                 // Field f2:I
       5: return

  public int f3();
    Code:
       0: getstatic     #28                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       3: ldc           #30                 // String def
       5: invokevirtual #34                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
       8: iconst_3
       9: ireturn

  public void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_2
       2: iconst_2
       3: istore_3
       4: getstatic     #28                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       7: iload_2
       8: invokestatic  #43                 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
      11: invokevirtual #34                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      14: return

  public Test();
    Code:
       0: aload_0
       1: invokespecial #50                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: getstatic     #28                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       8: ldc           #52                 // String val
      10: invokevirtual #34                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      13: iconst_1
      14: putfield      #14                 // Field f1:I
      17: aload_0
      18: getstatic     #28                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
      21: ldc           #54                 // String var
      23: invokevirtual #34                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
      26: iconst_2
      27: putfield      #18                 // Field f2:I
      30: return
}
从上面反编译的代码可以看出:

1)val是java的final不可变变量,var是java的普通变量;

2)在main函数里,val和var仅声明变量;

3)在class类定义里,val和var是先声明field存储空间,然后分别为他们定了同名的方法。

val 变量定义了 同名方法(类似于getter),来获取它的变量值;

public int f1();

var 变量定义了 同名方法(类似getter) 来获取它的变量值,同时提供了修改变量值的方法(类似于setter)

public int f2();
public void f2_$eq(int);

4)val/var和def的区别,可以从callByValue 和 callByName的角度来理解,val,var是callByValue, def是callByName.

callByValue 和callByName的区别,请移步:http://blog.csdn.net/qq_29343201/article/details/56281777






  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值