2016-04-08 15 views
5

У меня есть Scala Implicit класс из RecordService API, который я хотел использовать в файле Java.Как использовать неявный класс 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.*; 

Но я не в состоянии использовать recordServiceTextFile ("путь") от sparkContext.

В Scala импорт немного отличается и его работа.

+1

Я не вижу неявный класс. –

+0

Импорт кода Scala в Java-код не является тривиальной операцией для моих глаз. Это требует некоторого понимания внутренних компонентов javac. Также вопрос не ясен. Можете ли вы быть более ясными в вопросе? Чем более «полный» вопрос, тем лучше ответ. –

+0

@Ramesh Добро пожаловать, но это был не я. –

ответ

6

Вот простое определение неявного класса в объекте пакета

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

Спасибо, хорошо работает .. – Shankar

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 object.

Кроме того, точка стоит задуматься «Действительно ли это имеет смысл, чтобы определить то, что является доступным снаружи внутри объекта пакета?»

+0

ваш неявный класс отсутствует 'package' перед' object spark', вот основная проблема, с которой я столкнулся ... – Shankar

+0

Я добавил объяснение в ответ. Это то, над чем работает команда scala. –

1

package object spark компилируется в класс package в пакете spark. Неявный класс RecordServiceContext будет скомпилирован в статический метод RecordServiceContext (это неявный def scala) в package и класс package$RecordServiceContext.

Итак, следующий код должен это сделать:

import com.cloudera.recordservice.spark.*; 

//some code 

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

//some code 

Но package, вероятно, является зарезервированным ключевым словом, и Java не имеет возможности избежать их, насколько я знаю. Поэтому вам нужно будет сделать какое-то отражение, чтобы вызвать метод RecordServiceContext.

Смежные вопросы