Java中可见的Scala中的Package-private作用域

当我从 Java代码中使用Scala代码生成的字节码时,我刚刚发现了Scala范围很奇怪的行为.考虑使用Spark(Spark 1.4,Hadoop 2.6)的以下代码片段:
import java.util.Arrays;
import java.util.List;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.broadcast.broadcast;

public class Test {
    public static void main(String[] args) {
        JavaSparkContext sc = 
            new JavaSparkContext(new SparkConf()
                                .setMaster("local[*]")
                                .setAppName("test"));

        broadcast<List<Integer>> broadcast = sc.broadcast(Arrays.asList(1,2,3));

        broadcast.destroy(true);

        // fails with java.io.IOException: org.apache.spark.SparkException: 
        // Attempted to use broadcast(0) after it was destroyed
        sc.parallelize(Arrays.asList("task1","task2"),2)
          .foreach(x -> System.out.println(broadcast.getValue()));
    }
}

这个代码失败了,这是因为我在使用它之前自愿摧毁广播,但事实是,在我的心理模型中,它不应该编译,更不用说运行正常.

的确,broadcast.destroy(Boolean)被声明为private [spark],所以它不应该从我的代码可见.我会尝试看广播的字节码,但这不是我的专长,所以我更喜欢发表这个问题.另外,对不起,我太懒了,创建一个不依赖于Spark的例子,但至少你得到了这个想法.请注意,我可以使用Spark的各种包私有方法,而不仅仅是广播.

任何想法发生了什么?

解决方法

如果我们用一个更简单的例子来重构这个问题:
package yuvie

class X {
  private[yuvie] def destory(d: Boolean) = true
}

并在Java中反编译:

[yuvali@localhost yuvie]$javap -p X.class 
Compiled from "X.scala"
public class yuvie.X {
  public boolean destory(boolean);
  public yuvie.X();
}

我们看到Scala中的私有[package]在Java中公开.为什么?这来自于Java私有包不等同于Scala私有包的事实.有一个很好的解释in this post

The important distinction is that ‘private [mypackage]’ in Scala is
not
Java package-private,however much it looks like it. Scala
packages are truly hierarchical,and ‘private [mypackage]’ grants
access to classes and objects up to “mypackage” (including all the
hierarchical packages that may be between). (I don’t have the Scala
spec reference for this and my understating here may be hazy,I’m
using 07001 as a reference.) Java’s packages are not hierarchical,and
package-private grants access only to classes in that package,as well
as subclasses of the original class,something that Scala’s ‘private
[mypackage]’ does not allow.

So,‘package [mypackage]’ is both more and less restrictive that Java package-private. For both reasons,JVM package-private can’t be used to implement it,and the only option that allows the uses that Scala exposes in the compiler is ‘public.’

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...