Scala 构造函数中的最终变量
我对 Scala 还很陌生,但我知道你可以定义在构造函数中初始化的类变量,就像
class AClass(aVal: String)
在 java 中执行以下操作一样
class AClass {
private String aVal;
public AClass(String aVal) {
this.aVal = aVal;
}
}
。在 Java 中,我会将 aVal 声明为 Final。有没有办法在 Scala 语法中使 aVal 变量成为最终变量?
编辑:这是我编译以下 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
I'm still pretty new to Scala, but I know you can define class variables that are initialized in the constructor like
class AClass(aVal: String)
which would be like doing the following in java
class AClass {
private String aVal;
public AClass(String aVal) {
this.aVal = aVal;
}
}
In Java, I would declare aVal as final. Is there a way to make the aVal variable final in the Scala syntax?
EDIT: Here is what I am seeing when I compile the following Scala class:
class AClass(aVal: String) {
def printVal() {
println(aVal)
}
}
I ran javap -private
and got the output
public class AClass extends java.lang.Object implements scala.ScalaObject{
private final java.lang.String aVal;
public void printVal();
public AClass(java.lang.String);
}
When I change the scala class definition to have class AClass(**val** aVal: String)
I get the following output from 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);
}
The public method aVal
is generated. I'm still learning here - can anyone explain why that is generated?
Note I am using scala 2.9
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在此代码中,aVal 是最终变量。所以你已经有了一个最终变量。
在此代码中,aVal 是最终的,并且您有 aVAl 的 getter。所以你可以像下面一样使用它
最后,
在这段代码中,aVal不是最终的,你有aVal的getter和setter。所以你可以像下面这样使用它
In this code, aVal is a final variable. So You already have a final variable.
In this code, aVal is final and you have getter of aVAl. So you can use it like below
And finally,
In this code, aVal is not final and you have getter and setter of aVal. So you can use it like below
复制自我的答案:Scala Final 与 val 的并发可见性
术语
final
有两种含义:a) 对于 Scala 字段/方法和 Java 方法,它意味着“不能在subclass”和 b) 对于 Java 字段和 JVM 字节码来说,这意味着“该字段必须在构造函数中初始化并且不能重新分配”。用
val
标记的类参数(或者等效地,没有修饰符的情况类参数)在第二种意义上确实是最终的,因此是线程安全的。证明如下:
或者使用
javap
,可以方便地从 REPL 运行:如果非 case 类的类参数未标记为
val
或var
,并且它不被任何方法引用,它只需要对类的构造函数可见。然后,Scala 编译器可以自由地优化远离字节码的字段。在 Scala 2.9.1 中,这似乎有效:Copied from my answer: Scala final vs val for concurrency visibility
There are two meanings of the term
final
: a) for Scala fields/methods and Java methods it means "cannot be overridded in a subclass" and b) for Java fields and in JVM bytecode it means "the field must be initialized in the constructor and cannot be reassigned".Class parameters marked with
val
(or, equivalently, case class parameters without a modifier) are indeed final in second sense, and hence thread safe.Here's proof:
Or with
javap
, which can be conveniently run from the REPL:If the class parameter of a non-case class is not marked as a
val
orvar
, and it is not referred to from any methods, it need only be visible to the constructor of the class. The Scala compiler is then free to optimize the field away from the bytecode. In Scala 2.9.1, this appears to work: