【问题标题】:How to use Scala implicit class in Java如何在 Java 中使用 Scala 隐式类
【发布时间】: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 不客气,但那不是我。

标签: java scala cloudera-cdh


【解决方案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 团队正在做的事情。
        猜你喜欢
        • 2023-03-05
        • 2014-04-23
        • 2015-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-16
        相关资源
        最近更新 更多