2017-01-21 23 views
-1

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

+0

请有你正在做的代码段。 – marios

回答

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编译的新代码链接。

1

我一直在定义Scala类的私有和受保护的方法,但是当编译成java字节码时,它们只是消失,所有的方法都变成公共的!

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

就是这样。只要看看斯卡拉母语进行比较,其编译为本地二进制机器码:所有访问修饰符,并所有类型完全走了,因为根本没有办法来表示他们在本机二进制机器码。即使是Java,也无法在JVM字节码中正确表示(例如Java有泛型,但JVM无法表示它们)。

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

是的。当您使用Java与Scala代码进行交互时,您将绕过对Scala编译器的任何检查。这是没有办法的。

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

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

+0

谢谢您的意见!以下是我在谈论的一个例子: 类Person(){ 私人高清的run(){ } 保护的高清行走(英里的:int){ } } 在这种情况下,当使用Java或Scala编译的类(.class)时,这两种方法(walk和run)都会成为公有的方法。我知道同样的情况发生在泛型上,它们不是虚拟机的一个特性部分,但我个人发现修饰符比泛型更重要,没有泛型,甚至可以以旧的方式执行 – mingo

+0

即使是Java的'private'修饰符类(仅与嵌套类型相关)实际上并不存储在通常的访问修饰符字段中。它存储在一个专用于内部类的特殊属性中,由Reflection支持,而JVM本身不强制执行“私有”访问级别...... – Holger