如何在Java中使用Scala隐式类

6

我有一个来自RecordService API的Scala隐式类,想要在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中,导入方式略有不同,并且可以正常工作。


1
我没有看到一个隐式类。 - Jasper-M
将Scala代码导入Java代码对我来说并不是一项简单的操作。它需要对javac内部有一定的了解。此外,问题也不太清楚。你能否在问题上更加明确一些?问题描述得越详细,答案就会越好。 - Som Bhattacharyya
@Ramesh 不用谢,但那不是我。 - Jasper-M
4个回答

8
这是关于包对象中隐式类的简单定义。
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并添加一个额外的可调用方法。这是对隐式类的优化。

大致如下:

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

1

package object spark被编译为spark包中的package类。隐式类RecordServiceContext将被编译为package中的静态方法RecordServiceContext(这是Scala的implicit def),以及一个名为package$RecordServiceContext的类。

因此,以下代码应该可以实现:

import com.cloudera.recordservice.spark.*;

//some code

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

//some code

但是package可能是一个保留关键字,据我所知Java没有转义它们的方法。因此,您需要进行一些反射来调用RecordServiceContext方法。


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

0

这应该可以做到。

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

我已经修改了签名。

我的Scala类看起来像这样,

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

我的Java类看起来像这样:

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

编辑 ---

快速查看Scala变更请求,我们可以看到this

他们正在努力使在package object下定义的类与在常规package中定义的类行为相同。但这是针对尚未发布的2.12版本。

因此,他们建议仅将不需要任何外部交互的绝对必要的类/对象放在package对象中。否则,请将它们放在常规的包中。所以现在你需要不使用package object构造。

此外,值得思考的一点是,“在一个包对象内定义可以从外部访问的东西真的有意义吗?”


你的隐式类在object spark之前缺少package,这是我面临的主要问题... - Shankar
我在答案中添加了说明。这是Scala团队正在努力解决的事情。 - Som Bhattacharyya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接