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

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

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

Errors.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.

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();
Другие вопросы по тегам