如何在 Java 中使用 Scala 隐式 class

How to use Scala implicit class in Java

我有一个来自 RecordService API 的 Scala 隐式 class,我想在 Java 文件中使用它。

package object spark {

   implicit class RecordServiceContext(ctx: SparkContext) {
     def recordServiceTextFile(path: String) : RDD[String] = {
      new RecordServiceRDD(ctx).setPath(path)
          .map(v => v(0).asInstanceOf[Text].toString)
    }
  }

}

现在我正在尝试使用下面的导入将其导入到 Java 文件中。

import com.cloudera.recordservice.spark.*;

但是我无法使用 sparkContext 中的 recordServiceTextFile("path")。

在 Scala 中,导入和它的工作方式略有不同。

 SparkContext ctx = ...
 RecordServiceContext rsct = new RecordServiceContext(ctx)
 recordServiceTextFile("/your_path")

这应该可以做到。

String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf");

虽然我更改了签名。

我的 Scala class 看起来像这样,

object spark {
implicit class RecordServiceContext(ctx: String) {
 def recordServiceTextFile(path: String) : String = {
 "test"
}
}
}

我的javaclass是这样的,

 public class TestScalaCall {
public static void main(String args[]){
    String s = new spark.RecordServiceContext("safa").recordServiceTextFile("dsf");
}
}

编辑---

因此,快速查看 Scala 更改请求向我们展示了 this

他们实际上正在努力使在 package object 下定义的 class 的行为方式与在常规 package 中定义它的方式相同。但这是针对尚未发布的 2.12 .

因此他们给出的建议是只保留绝对必要的 classes/objects,不需要在包对象内部进行任何外部交互。否则将它们放在常规包装下。 所以现在你不需要使用 package object 结构。

另外,值得深思的一点"Does it really make sense to define something that is accessible on the outside inside a package object ? "

一个package object spark在包spark中被编译成一个classpackage。隐式 class RecordServiceContext 将在 package 和 class package$RecordServiceContext 中编译为静态方法 RecordServiceContext (这是 scala 的隐式定义)。 =20=]

所以下面的代码应该可以做到:

import com.cloudera.recordservice.spark.*;

//some code

RDD<String> rdd = package.RecordServiceContext(myContext).recordServiceTextFile(pathToFile);

//some code

但是package可能是一个保留关键字,据我所知Java没有办法转义它们。因此,您必须进行一些反思才能调用 RecordServiceContext 方法。

这里是包对象

中隐式class的简单定义
package object spark {
  implicit class Ext(param: Int) {
    def a = param + 1
  }
}

这是 java

中的使用方法
public class Test {
    public static void main(String[] args) {
        spark.package$.MODULE$.Ext(123).a();
    }
}

所以你基本上可以使用 RecordServiceContext 作为包装你的 SparkContext 的方法并添加一个你可以调用的额外方法。这是对隐式 classes.

的优化

那就是这样的:

SparkContext c = ???
RDD<String> rdd = com.cloudera.recordservice.spark.package$.MODULE$.RecordServiceContext(c)
   .recordServiceTextFile("asdf");