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