Байт-код класса Sealed Trait / Object Case Изменен по сравнению с 2.9.1. на 2.9.2?

Один и тот же исходный файл в обоих каталогах

У меня есть следующая запечатанная черта в Errors.scala, на которую я хотел бы ссылаться в классе Java. В Scala 2.9.1 я мог ссылаться на Errors.TooBig из Java как на Errors$TooBig$, который больше не компилируется в версии 2.9.2.

Ошибки.scala

package com.abc

sealed trait Error

object Errors {
  case object TooBig extends Error
}

JavaTest.java

import com.abc.Errors$TooBig$;
public class JavaTest {
}

У меня есть одни и те же исходные файлы в двух разных каталогах (2.9.1/2.9.2). Я могу скомпилировать исходный код, используя 2.9.1, но не 2.9.2.

>2.9.1$ brew switch scala 2.9.1
>2.9.1$ scalac Errors.scala
>2.9.1$ javac -classpath .:/usr/local/Cellar/scala/2.9.1/libexec/lib/scala-library.jar JavaTest.java
>2.9.1$
>2.9.1$ cd ../2.9.2
>2.9.2$ brew switch scala 2.9.2
>2.9.2$ scalac Errors.scala
>2.9.2$ javac -classpath .:/usr/local/Cellar/scala/2.9.2/libexec/lib/scala-library.jar JavaTest.java
JavaTest.java:1: cannot find symbol
symbol  : class Errors$TooBig$
location: package com.abc
import com.abc.Errors$TooBig$;
              ^
1 error
}
}

Вот разница дампа javap файлов класса com.abc.Errors$TooBig$:

mhughes:~/scalatest$ diff 2.9.1/TooBig.txt 2.9.2/TooBig.txt 
2c2
< public final class com.abc.Errors$TooBig$ extends java.lang.Object implements com.abc.Error,scala.ScalaObject,scala.Product,scala.Serializable
---
> public final class com.abc.Errors$TooBig$ extends java.lang.Object implements com.abc.Error,scala.Product,scala.Serializable
5a6,7
>   InnerClass: 
>    public final #68= #9 of #67; //TooBig$=class com/abc/Errors$TooBig$ of class com/abc/Errors
73,80c75,84
< const #65 = Asciz com/abc/Error;
< const #66 = class #65;    //  com/abc/Error
< const #67 = Asciz scala/ScalaObject;
< const #68 = class #67;    //  scala/ScalaObject
< const #69 = Asciz scala/Product;
< const #70 = class #69;    //  scala/Product
< const #71 = Asciz scala/Serializable;
< const #72 = class #71;    //  scala/Serializable
---
> const #65 = Asciz InnerClasses;
> const #66 = Asciz com/abc/Errors;
> const #67 = class #66;    //  com/abc/Errors
> const #68 = Asciz TooBig$;
> const #69 = Asciz com/abc/Error;
> const #70 = class #69;    //  com/abc/Error
> const #71 = Asciz scala/Product;
> const #72 = class #71;    //  scala/Product
> const #73 = Asciz scala/Serializable;
> const #74 = class #73;    //  scala/Serializable

Вы можете видеть, что явно существует класс с именем «Errors$TooBig$», сгенерированный как 2.9.1, так и 2.9.2.


person Matt Hughes    schedule 14.06.2012    source источник


Ответы (1)


Вы не должны полагаться на имена классов для получения объектов scala из Java. Вы можете написать статическую фабрику, предназначенную для вызова из Java:

package com.abc

sealed trait Error

object Errors {
  case object TooBig extends Error

  //Java API
  def getTooBig(): Error = TooBig
}

Затем вызовите его из Java с помощью:

import com.abc.*;

Error tooBig = Errors.getTooBig();
person paradigmatic    schedule 14.06.2012