scala中val与def定义的区别
2018-02-06 12:06
204 查看
scala中val与def定义的区别
变量
val定义一个不可改变的变量,
def则是一个方法:
//scala中定义: def main(args: Array[String]): Unit = { def a = "hello" val b = "hello" println(a) println(b) } //编译之后的class文件 private final String a$1() { return "hello"; } public void main(String[] args) { String b = "hello"; Predef..MODULE$.println(a$1()); Predef..MODULE$.println(b); }
方法
下面我们分别对应这四种定义方式,与反编译后的java比较一下,从而深层次理解def与val在方法中怎么实现的class Test { def even1: (Int => Boolean) = (_ % 2 == 0) val even2: (Int => Boolean) = (_ % 2 == 0) def even3(x: Int): Boolean = { x % 2 == 0 } lazy val even4: Int => Boolean = _ % 2 == 0 }
1. def a = ()
def even1: (Int => Boolean) = (_ % 2 == 0), 通过编译我们可以看到,每次调用even1 都会实例化一个对象,这显然不是我们愿意看到的
public Function1<Object, Object> even1() { new AbstractFunction1.mcZI.sp() { public static final long serialVersionUID = 0L; public boolean apply$mcZI$sp(int x$1) { return x$1 % 2 == 0; } public final boolean apply(int x$1) { return apply$mcZI$sp(x$1); } }; }
2. val =
val even2: (Int => Boolean) = (_ % 2 == 0),实现了Function1, 并且实例化该对象
public Function1<Object, Object> even2() { return this.even2; } private final Function1<Object, Object> even2 = new AbstractFunction1.mcZI.sp() { public static final long serialVersionUID = 0L; public boolean apply$mcZI$sp(int x$2) { return x$2 % 2 == 0; } public final boolean apply(int x$2) { return apply$mcZI$sp(x$2); } };
3.def a() = {}
这种方法定义相比java比较常规,容易接受def even3(x: Int): Boolean = { x % 2 == 0 } 编译之后如下: public class Test { public boolean even3(int x) { return x % 2 == 0; } }
4.lazy val
lazy val even4: Int => Boolean = _ % 2 == 0,对比even2, 实现了懒加载
private Function1<Object, Object> even4; private volatile boolean bitmap$0; public Function1<Object, Object> even4() { return this.bitmap$0 ? this.even4 : even4$lzycompute(); } private Function1 even4$lzycompute() { synchronized (this) { if (!this.bitmap$0) { this.even4 = new AbstractFunction1.mcZI.sp() { public static final long serialVersionUID = 0L; public boolean apply$mcZI$sp(int x$1) { return x$1 % 2 == 0; } public final boolean apply(int x$1) { return apply$mcZI$sp(x$1); } };this.bitmap$0 = true; } return this.even4; } }
我们再看一个比较复杂的例子
方法里面定义方法class Test { def fun1(x: Int): Int = { def fun1_2() = { println("fun1_2=>" + x) } fun1_2() println("fun1") 2 * x } val fun2 = (x: Int) => { val fun2_2 = () => { println("fun2_2=>" + x) } fun2_2() println("fun2") 2 * x } }
反编译后的java代码如下:
public class Test { private final void fun1_2$1(int x$1) { Predef..MODULE$.println(new StringBuilder().append("fun1_2=>").append(BoxesRunTime.boxToInteger(x$1)).toString()); } public int fun1(int x) { fun1_2$1(x); Predef..MODULE$.println("fun1"); return 2 * x; } public Function1<Object, Object> fun2() { return this.fun2; } private final Function1<Object, Object> fun2 = new AbstractFunction1.mcII.sp() { public static final long serialVersionUID = 0L; public final int apply(int x) { return apply$mcII$sp(x); } public int apply$mcII$sp(final int x) { Function0 fun2_2 = new AbstractFunction0.mcV.sp() { public static final long serialVersionUID = 0L; public final void apply() { apply$mcV$sp(); } public void apply$mcV$sp() { Predef..MODULE$.println(new StringBuilder().append("fun2_2=>").append(BoxesRunTime.boxToInteger(x)).toString()); } }; fun2_2.apply$mcV$sp(); Predef..MODULE$.println("fun2"); return 2 * x; } }; }
从例子可以看出来,
def方法比较简单唯一的区别是,把方法提出去形成并列的两个方法,把这种闭包形式通过形参的方式传递给下一个方法, 而
val方法通过实例化Function1接口来实现,对于fun2_2每次调用都会实例化对象,这个使我们编程中需要注意的
相关文章推荐
- scala关键字val、var、def的区别
- scala 中的def/val/lazy val/的区别,call-by-value/call-by-name
- Scala变量定义val与var的区别
- scala def/val/lazy val区别以及call-by-name和call-by-value
- DLL中__declspec(dllexport)和.def(模块定义文件)定义导出函数的一点区别
- Scala中val和var的区别
- Scala中的var val/def
- Scala中的var val/def
- scala 学习(五)——def和procedure的区别和使用
- 2017.10.16 Scala中val和var的区别
- 在Scala中,def foo = {}和def foo() = {}有什么区别?
- Scala 中的val 与 var 的区别 immutable 与 mutable 的 区别
- scala val 与var 区别
- scala 中的val 、 var 、def
- 随感---如何理解Scala中的val与def
- js中定义变量的三种方式const,val,let 的区别
- Scala中val和var的区别
- Scala方法定义,方法和函数的区别,将方法转换成函数
- scala val 和 var的区别
- Scala :关于重新定义 val 变量