Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
构造函数中的Scala最终变量_Scala_Constructor_Final - Fatal编程技术网

构造函数中的Scala最终变量

构造函数中的Scala最终变量,scala,constructor,final,Scala,Constructor,Final,我对Scala还是相当陌生,但我知道可以定义在构造函数中初始化的类变量,如 class AClass(aVal: String) 这就像在java中执行以下操作一样 class AClass { private String aVal; public AClass(String aVal) { this.aVal = aVal; } } 在Java中,我将声明aVal为final。有没有办法使aVal变量在Scala语法中成为final 编辑:以下是

我对Scala还是相当陌生,但我知道可以定义在构造函数中初始化的类变量,如

class AClass(aVal: String)
这就像在java中执行以下操作一样

class AClass {
    private String aVal;

    public AClass(String aVal) {
        this.aVal = aVal;
    }
}
在Java中,我将声明aVal为final。有没有办法使aVal变量在Scala语法中成为final

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

class AClass(aVal: String) {
  def printVal() {
    println(aVal)
  }
}
我运行了
javap-private
,得到了输出

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

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

class AClass(aVal: String)
在这段代码中,aVal是最后一个变量。所以你已经有了最后一个变量

class AClass(val aVal: String)
在这段代码中,aVal是最终的,您有aVal的getter。所以你可以像下面那样使用它

scala> val a= new AClass("aa")
a: A1 = A1@1d7d58f

scala> a.aVal
res2: String = aa
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
最后

class AClass(var aVal: String)
在这段代码中,aVal不是最终的,您有aVal的getter和setter。所以你可以像下面那样使用它

scala> val a= new AClass("aa")
a: A1 = A1@1d7d58f

scala> a.aVal
res2: String = aa
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
摘自我的回答:

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

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

以下是证据:

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运行:

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);
}

Ug。我一定忘了重新编译,然后用较旧的实现()的行为证实了我的发现。你确实是对的。我提到的关于子类能够覆盖VAL的问题(这是final的一个问题)由于底层字段是私有的,并且生成的类中的访问器覆盖了父类中的访问器(不是final)而得以避免。谢谢你直截了当地说。