我有以下scala代码。我把错误放在MAX_DATA_PAGE_SIZE定义之后的CLASS_TYPE上。我认为这不能编译,或者它可以给出正确的答案,但输出0,为什么会发生这种情况?
object hello extends App{
val baseSize = 256
val MIN_DATA_PAGE_SIZE = math.max(baseSize, 1024)
val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
val CLASS_TYPE: Int = 2
println(MAX_DATA_PAGE_SIZE)
}
答案 0 :(得分:1)
编译器在编译时给出了警告,例如
[warn] Reference to uninitialized value CLASS_TYPE
[warn] val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
[warn] ^
[warn] one warning found
解决此问题的最佳方法是使用更严格的编译器选项。添加到build.sbt
scalacOptions ++= Seq(
"-unchecked",
"-deprecation",
"-feature",
"-Xfatal-warnings",
"-language:postfixOps",
"-Ywarn-unused-import"
)
另请注意,根据scala style,你应该注意你的常量,如
MaxDataPageSize
ClassType
等等。
答案 1 :(得分:1)
你是对的,由于未初始化的变量用法,这不能用C ++这样的语言编译。正如德米特里的回答所提到的那样,编译器会警告你。然而,scala编译成Java,如下所示:
~$ scalac -print hello.scala
hello.scala:4: warning: Reference to uninitialized value CLASS_TYPE
val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
^
[[syntax trees at end of cleanup]] // hello.scala
package <empty> {
object hello extends Object with App {
<stable> <accessor> def executionStart(): Long = hello.this.executionStart;
@deprecatedOverriding("executionStart should not be overridden", "2.11.0") private[this] val executionStart: Long = _;
final <accessor> def _args(): Array[String] = hello.this._args;
private[this] var _args: Array[String] = _;
final <accessor> def _args_=(x$1: Array[String]): Unit = {
hello.this._args = x$1;
()
};
final <stable> <accessor> def initCode(): scala.collection.mutable.ListBuffer = hello.this.initCode;
private[this] val initCode: scala.collection.mutable.ListBuffer = _;
<accessor> def scala$App$_setter_$executionStart_=(x$1: Long): Unit = {
hello.this.executionStart = x$1;
()
};
<accessor> def initCode_=(x$1: scala.collection.mutable.ListBuffer): Unit = {
hello.this.initCode = x$1;
()
};
@deprecatedOverriding("args should not be overridden", "2.11.0") def args(): Array[String] = scala.App$class.args(hello.this);
@deprecated("The delayedInit mechanism will disappear.", "2.11.0") override def delayedInit(body: Function0): Unit = scala.App$class.delayedInit(hello.this, body);
@deprecatedOverriding("main should not be overridden", "2.11.0") def main(args: Array[String]): Unit = scala.App$class.main(hello.this, args);
private[this] val baseSize: Int = _;
<stable> <accessor> def baseSize(): Int = hello.this.baseSize;
private[this] val MIN_DATA_PAGE_SIZE: Int = _;
<stable> <accessor> def MIN_DATA_PAGE_SIZE(): Int = hello.this.MIN_DATA_PAGE_SIZE;
private[this] val MAX_DATA_PAGE_SIZE: Int = _;
<stable> <accessor> def MAX_DATA_PAGE_SIZE(): Int = hello.this.MAX_DATA_PAGE_SIZE;
private[this] val CLASS_TYPE: Int = _;
<stable> <accessor> def CLASS_TYPE(): Int = hello.this.CLASS_TYPE;
final <synthetic> def delayedEndpoint$hello$1: Unit = {
hello.this.baseSize = 256;
hello.this.MIN_DATA_PAGE_SIZE = scala.math.`package`.max(hello.this.baseSize(), 1024);
hello.this.MAX_DATA_PAGE_SIZE = hello.this.MIN_DATA_PAGE_SIZE().*(scala.math.`package`.pow(2.0, hello.this.CLASS_TYPE().-(1).toDouble()).toInt());
hello.this.CLASS_TYPE = 2;
scala.this.Predef.println(scala.Int.box(hello.this.MAX_DATA_PAGE_SIZE()));
()
};
def <init>(): hello.type = {
hello.super.<init>();
scala.App$class./*App$class*/$init$(hello.this);
hello.this.delayedInit(new hello$delayedInit$body(hello.this));
()
}
};
final <synthetic> class hello$delayedInit$body extends runtime.AbstractFunction0 {
<paramaccessor> private[this] val $outer: hello.type = _;
final def apply(): Object = {
hello$delayedInit$body.this.$outer.delayedEndpoint$hello$1();
scala.runtime.BoxedUnit.UNIT
};
def <init>($outer: hello.type): hello$delayedInit$body = {
if ($outer.eq(null))
throw null
else
hello$delayedInit$body.this.$outer = $outer;
hello$delayedInit$body.super.<init>();
()
}
}
}
one warning found
这不会导致编译错误,但肯定是未定义的行为。
如果您将该类加载到REPL并运行两次,则会给出正确答案,因为CLASS_TYPE
已正确初始化。
scala> :load -v hello.scala
Loading hello.scala...
scala> object hello extends App{
| val baseSize = 256
| val MIN_DATA_PAGE_SIZE = math.max(baseSize, 1024)
| val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
| val CLASS_TYPE: Int = 2
|
| println(MAX_DATA_PAGE_SIZE)
| }
<console>:10: warning: Reference to uninitialized value CLASS_TYPE
val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
^
defined object hello
scala> hello.main(Array())
0
scala> hello.main(Array())
2048
这与编译扩展App trait的对象的方式有关。
如果您编写了这样的普通应用程序:
object hello {
def main(args:Array[String]) {
val baseSize = 256
val MIN_DATA_PAGE_SIZE = math.max(baseSize, 1024)
val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
val CLASS_TYPE: Int = 2
println(MAX_DATA_PAGE_SIZE)
}
}
并尝试编译它会出现以下错误:
~$ scalac hello.scala
hello.scala:6: error: forward reference extends over definition of value MAX_DATA_PAGE_SIZE
val MAX_DATA_PAGE_SIZE = MIN_DATA_PAGE_SIZE * scala.math.pow(2, CLASS_TYPE-1).toInt
^
one error found