def和var / val对于匿名函数有什么区别

时间:2016-03-23 04:50:58

标签: scala

我对匿名函数定义感到困惑如下:

var plusOne = (x:Int)=>x+1
// or val plusOne=(x:Int)=>x+1
println(plusOne(2))

或者

def plusOne = (x:Int)=>x+1
println(plusOne(2))

对于函数名称,请var / valdef之间有什么区别。

4 个答案:

答案 0 :(得分:5)

  • val 声明不允许重新分配的“不可变变量或更确切的符号”,立即评估分配的右侧
  • var 声明一个“可变变量”,允许稍后重新分配给符号,分配的右侧就像val一样立即评估
  • def 声明一个不允许重新分配的“不可变符号”,右侧被懒惰地评估,即在代码中稍后引用该符号时

示例 -

var plusOneVar = (x:Int)=>x+1
val plusOneVal = (x:Int)=>x+1
def plusOneDef = (x:Int)=>x+1

plusOneVar = (x:Int)=>x+2 // Reassignment to var is valid
plusOneVal = (x:Int)=>x+2 // Compile time error, reassignment to val
plusOneDef = (x:Int)=>x+2 // Compile time error, reassignment to val

因为您正在查看具有函数的示例,所以很难理解。让我们尝试用简单的变量来理解它。

var symbolVar = 100        // line 1
val symbolVal = symbolVar  // line 2
def symbolDef = symbolVar  // line 3

println(symbolVar)  // prints 100
println(symbolVal)  // prints 100
println(symbolDef)  // prints 100 - no surprise yet

symbolVar = symbolVar + 1

println(symbolVal)  // still prints 100 which was evaluated and assigned on line 2
println(symbolDef)  // prints 101 as symbolDef is a def and it depends on symbolVar, line 3 is evaluated again

答案 1 :(得分:2)

可以重新分配。 var plusOne无法重新分配。两者都被评估一次。每次调用val plusOne时都会对其进行评估

答案 2 :(得分:1)

还要注意val(或var)函数的一个实例被创建并用于该函数的任意数量的调用,而def是一个新的实例。为每次调用创建函数。然而,对于

def f (i:Int) = i+1
f: (i: Int)Int

注意

val g = f _
g: Int => Int = <function1>

答案 3 :(得分:0)

使用javap从类文件反汇编程序结果中可以清楚地看出。将以下代码保存为Test.scala

class Test {
  val fVal: Int => Int = x => x + 1
  var fVar: Int => Int = x => x + 1
  def fDef(x: Int): Int = { x + 1 }
}

并且scalac Test.scala; javap Test会显示

Compiled from "Test.scala"
public class Test {
  public scala.Function1<java.lang.Object, java.lang.Object> fVal();
  public scala.Function1<java.lang.Object, java.lang.Object> fVar();
  public void fVar_$eq(scala.Function1<java.lang.Object, java.lang.Object>);
  public int fDef(int);
  public Test();
}

如上面的结果所示,valfVar表示为返回Function1对象的方法。区别在于fVar有一个额外的&#34; setter&#34;。虽然fDef与普通的Java方法类似。