如何在 Java 中使用 Scala 隐式类

Posted

技术标签:

【中文标题】如何在 Java 中使用 Scala 隐式类【英文标题】:How to use Scala implicit class in Java 【发布时间】:2016-04-08 10:58:28 【问题描述】:

我有一个来自 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 中,导入和它的工作方式略有不同。

【问题讨论】:

我没有看到隐式类。 在 Java 代码中导入 Scala 代码在我看来并不是一件小事。它需要对 javac 内部结构有所了解。问题也不清楚。你能在这个问题上更清楚一点吗?问题越“完整”,答案就越好。 @Ramesh 不客气,但那不是我。 【参考方案1】:

这是包对象中隐式类的简单定义

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");

【讨论】:

【参考方案2】:

package object spark 编译为包spark 中的类package。隐式类 RecordServiceContext 将被编译为 package 中的静态方法 RecordServiceContext(这是 scala 的隐式定义)和类 package$RecordServiceContext

所以下面的代码应该做到这一点:

import com.cloudera.recordservice.spark.*;

//some code

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

//some code

但是package 可能是一个保留关键字,据我所知,Java 无法转义它们。所以你必须做一些反射来调用RecordServiceContext 方法。

【讨论】:

【参考方案3】:
 SparkContext ctx = ...
 RecordServiceContext rsct = new RecordServiceContext(ctx)
 recordServiceTextFile("/your_path")

【讨论】:

【参考方案4】:

应该这样做。

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 object 构造。

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

【讨论】:

你的隐式类在object spark 之前缺少package,这是我面临的主要问题...... 我在答案中添加了解释。这是 scala 团队正在做的事情。

以上是关于如何在 Java 中使用 Scala 隐式类的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中使用 Scala 隐式类

如何在 Java 中使用 Scala 隐式类

外键和引用类如何在 Hibernate 实体中一起存在?

随机森林分类如何在幕后工作?

serversocket 类如何在同一个端口上服务多个客户端连接?

JVM:Scala的JavaConversions如何在Java代码中运行?