Java和Scala与私有修饰符集成

时间:2017-01-21 00:07:43

标签: java scala bytecode access modifiers

我一直在从Scala类中定义私有和受保护的方法,但是在编译为java字节码时,它们只会消失并且所有方法都会公开!所以当从java调用时,我可以调用它们中的任何一个。我说的是对的吗?如果是这样,那么在不久的将来会有一个新的编译器改变吗?

2 个答案:

答案 0 :(得分:1)

  

我一直在使用Scala类定义私有和受保护的方法,但是在编译为java字节码时,它们只会消失并且所有方法都会公开!

Scala的访问修饰符语义不能映射到JVM的访问修饰符语义。任何翻译方法都必须是近似值。有时,最接近的可能近似值为public

这就是它的方式。只需查看Scala-native进行比较,它将编译为本机二进制机器代码:所有访问修饰符,而所有类型完全已消失,因为根本没有办法在本机二进制机器代码中表示它们。即使Java也无法在JVM字节码中正确表示(例如,Java具有泛型,但JVM无法表示它们)。

  

所以当从java调用时,我可以调用它们中的任何一个。我说的是对的吗?

是。当您使用Java与Scala代码进行交互时,您正在绕过Scala编译器所做的任何检查。没有办法解决这个问题。

  

如果是这样,那么在不久的将来会有新的编译器改变吗?

没有。它需要更改JVM规范,以允许语言指定自己的访问修饰符语义。我没有看到这种情况发生。

答案 1 :(得分:0)

有时会扩大访问权限,而不会进行任何名称修改或混淆。

在这里,您可能希望实现显示默认包访问:

scala> :pa
// Entering paste mode (ctrl-D to finish)

package p { class C { private[p] def c = 42 }}

// Exiting paste mode, now interpreting.


scala> :javap p.C
[snip]
  public int c();

这里提供了一个特殊的访问器来进行模式匹配:

scala> case class C(private val c: Int)
defined class C

scala> :javap -pv C
[snip]
  private final int c;
    descriptor: I
    flags: ACC_PRIVATE, ACC_FINAL

  public int c$access$0();

为了一般互操作的目的,依赖任何这样的实现细节并不是一个好主意。但是,Scala承诺在2.12.x等发行版系列中实现二进制兼容性。使用2.12.1编译的任何内容都必须与使用2.12.2编译的新代码链接。