用户定义的值类从Java看起来是什么样的?

Pth*_*ame 8 java interop scala scala-java-interop newtype

我想通过与Haskell的比较,我理解Scala 2.10的新"值类"特性newtype:

trait BoundedValue[+This] extends Any { this: This =>

  def upperBound: This

  def lowerBound: This

}

class Probability @throws(classOf[IllegalArgumentException]) (v: Double) extends AnyVal with BoundedValue[Probability] {

  val value: Double = if ((v >= 0.0) && (v <= 1.0)) v else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]")

  override val upperBound: Probability = new Probability(0.0)

  override val lowerBound: Probability = new Probability(1.0)

  // Implement probability arithmetic here;
  // will be represented by Double at runtime.

}
Run Code Online (Sandbox Code Playgroud)

我的问题是,值类如何出现在使用Scala包的Java代码中?值类是从Java端显示为引用类,还是完全擦除(因此它显示为它包装的类型)?换句话说,当Java涉及源级别时,值类是如何类型安全的?


编辑

根据SIP-15文档(在Daniel的答案中链接),上面的代码不会编译,因为值类不允许有任何初始化逻辑,因为要么v必须显式为val,要么Probability必须有一个unbox方法和相应的box它的伴随对象的方法,因为值类必须只有一个字段.正确的代码是:

trait BoundedValue[This <: BoundedValue[This]] extends Any { this: This =>

  def upperBound: This

  def lowerBound: This

}

class Probability private[Probability] (value: Double) extends AnyVal with BoundedValue[Probability] {

  @inline override def upperBound: Probability = new Probability(0.0)

  @inline override def lowerBound: Probability = new Probability(1.0)

  @inline def unbox: Double = value

  // Implement probability arithmetic here;
  // will be represented by Double at runtime (mostly).

}

object Probability {

  @throws(classOf[IllegalArgumentException])
  def box(v: Double): Probability = if ((v >= 0.0) && (v <= 1.0)) new Probability(v) else throw new IllegalArgumentException((v.toString) + "is not within the range [0.0, 1.0]")

}
Run Code Online (Sandbox Code Playgroud)

然而,问题本身仍然有效.

Dan*_*ral 6

值类编译为普通类,并且可能显示为引用.

它们的神奇之处在于,当值类没有逃避范围时,它的所有痕迹都会从代码中删除,从而有效地内联所有代码.当然,还提供额外的类型安全性.

另见SIP-15,它解释了机制.

  • 一个同样有趣的问题是"如何在没有值类型的平台(例如JVM)上编码Scala值类型"是"Scala值类型如何在*本身具有值类型的平台上编码(例如CLI) )".例如,可以通过在CLI上编译为结构的Scala值类型吗?是否保证它们*总是*被编译成结构体? (2认同)
  • 根据我的理解,这是不正确的,逃避范围的值类将被加框(我的意思是,该值将被包装在一个对象中,而不是内联).事实上,这个值"几乎总是"内联:-)查看我的问题的答案[在这些情况下,Scala值类将被"装箱",对吗?](http://stackoverflow.com/q/15860179/ 694469) (2认同)