首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >构造函数中的Scala最终变量

构造函数中的Scala最终变量
EN

Stack Overflow用户
提问于 2011-10-02 10:47:18
回答 2查看 4K关注 0票数 6

我仍然是Scala的新手,但我知道您可以定义在构造函数中初始化的类变量,如下所示

代码语言:javascript
复制
class AClass(aVal: String)

,这类似于在java中执行以下操作:

代码语言:javascript
复制
class AClass {
    private String aVal;

    public AClass(String aVal) {
        this.aVal = aVal;
    }
}

在Java语言中,我会将aVal声明为final。在Scala语法中,有没有办法让aVal变量成为final?

编辑:以下是我在编译以下Scala类时看到的内容:

代码语言:javascript
复制
class AClass(aVal: String) {
  def printVal() {
    println(aVal)
  }
}

我运行javap -private并获得输出

代码语言:javascript
复制
public class AClass extends java.lang.Object implements scala.ScalaObject{
  private final java.lang.String aVal;
  public void printVal();
  public AClass(java.lang.String);
}

当我将scala类定义更改为使用class AClass(**val** aVal: String)时,将从javap -private获得以下输出

代码语言:javascript
复制
public class AClass extends java.lang.Object implements scala.ScalaObject{
  private final java.lang.String aVal;
  public java.lang.String aVal();
  public void printVal();
  public AClass(java.lang.String);
}

生成公共方法aVal。我在这里还在学习--谁能解释一下为什么会这样呢?

注意,我使用的是scala 2.9

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-02 10:59:21

代码语言:javascript
复制
class AClass(aVal: String)

在这段代码中,aVal是最后一个变量。所以你已经有了一个最后一个变量。

代码语言:javascript
复制
class AClass(val aVal: String)

在这段代码中,aVAl是最终的,您有aVal的getter。所以你可以像下面这样使用它

代码语言:javascript
复制
scala> val a= new AClass("aa")
a: A1 = A1@1d7d58f

scala> a.aVal
res2: String = aa

最后,

代码语言:javascript
复制
class AClass(var aVal: String)

在这段代码中,aVal不是最终的,您有aVal的getter和setter。所以你可以像下面这样使用它

代码语言:javascript
复制
scala> val a= new AClass("aa")
a: AClass = AClass@1c059f6

scala> a.aVal
res3: String = aa

scala> a.aVal = "bb"
a.aVal: String = bb

scala> a.aVal
res4: String = bb
票数 11
EN

Stack Overflow用户

发布于 2011-10-02 22:31:38

从我的答案中复制:Scala final vs val for concurrency visibility

术语final有两种含义: a)对于Scala字段/方法和Java方法,它的意思是“不能在子类中被覆盖”;b)对于Java字段,在JVM字节码中,它意味着“字段必须在构造函数中初始化,并且不能被重新分配”。

val标记的类参数(或者,等价地,不带修饰符的case类参数)在第二种意义上确实是最终的,因此线程安全。

以下是证据:

代码语言:javascript
复制
scala>  class A(val a: Any); class B(final val b: Any); class C(var c: Any)
defined class A
defined class B
defined class C

scala> import java.lang.reflect._
import java.lang.reflect._

scala> def isFinal(cls: Class[_], fieldName: String) = {
     |   val f = cls.getDeclaredFields.find(_.getName == fieldName).get
     |   val mods = f.getModifiers
     |   Modifier.isFinal(mods)
     | }
isFinal: (cls: Class[_], fieldName: String)Boolean

scala> isFinal(classOf[A], "a")
res32: Boolean = true

scala> isFinal(classOf[B], "b")
res33: Boolean = true

scala> isFinal(classOf[C], "c")
res34: Boolean = false

或者使用javap,它可以很方便地从REPL运行:

代码语言:javascript
复制
scala> class A(val a: Any)
defined class A

scala> :javap -private A
Compiled from "<console>"
public class A extends java.lang.Object implements scala.ScalaObject{
    private final java.lang.Object a;
    public java.lang.Object a();
    public A(java.lang.Object);
}

如果非case类的类参数未标记为valvar,并且没有从任何方法中引用,则只需对该类的构造函数可见。然后,Scala编译器可以自由地优化字节码之外的字段。在Scala 2.9.1中,这似乎是可行的:

代码语言:javascript
复制
scala> class A(a: Any)
defined class A

scala> :javap -private A
Compiled from "<console>"
public class A extends java.lang.Object implements scala.ScalaObject{
    public A(java.lang.Object);
}
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7624302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档