在Java中使用Scala 2.10.1值类型

fbl*_*fbl 9 java scala compiler-errors value-type

我正在将2.9.*项目更新为2.10.我有几个基本类型(角度,长度等)的类,看起来它们是值类型的完美候选者.不幸的是,我使用这些类型的Java代码没有编译,我无法弄清楚原因.我把它简化为一组非常简单的代码.任何建议将不胜感激.

角度类定义(scala)

package com.example.units

class Angle(val radians : Double) extends AnyVal
{
  def degrees = radians * 180.0 / math.Pi
}

object Angle
{
  val Zero = new Angle(0)
}
Run Code Online (Sandbox Code Playgroud)

角度测试用例(用Java编写的痛苦)

package com.example.units;

import junit.framework.Assert;
import org.junit.Test;

public class AngleTest
{
    @Test
    public static void TestZero()
    {
        Angle a = Angle.Zero();
        Assert.assertEquals(a.degrees(), 0, 1E-9);

    }

}
Run Code Online (Sandbox Code Playgroud)

当我编译时,我收到此错误:

AngleTest.java:19 incompatible types
found :double
required: com.example.units.Angle
Angle a = Angle.Zero();

            ^
Run Code Online (Sandbox Code Playgroud)

它看起来好像Angle.Zero被返回为double,而不是Angle.我尝试添加box/unbox方法,但继续收到相同的错误.再次,任何帮助将不胜感激.

Ale*_*ula 10

Scala编译器将值类转换为未装箱类型,从而消除了运行时的成本.检查已编译的类文件Angle,您将看到:

public static double Zero();
Run Code Online (Sandbox Code Playgroud)

所以从Java的角度来看,Angle.Zero返回一个double; 它不知道Scala的值类的语义.

Angle自己的方法,例如degrees,被编译成a)一个静态扩展方法,它接受unboxed值(double)b)一个实例方法:

public static double degrees$extension(double);
public double degrees();
Run Code Online (Sandbox Code Playgroud)

这意味着后者仍然可以Angle在Java 的实例上调用:

Angle a = new Angle(0);
Assert.assertEquals(a.degrees(), 0, 1E-9);
Run Code Online (Sandbox Code Playgroud)

  • IMO Scala做得对,Java搞砸了."原始"和"对象"类型之间区别的整个概念是有缺陷的. (4认同)