简体   繁体   English

从 Scala 代码调用 java 通用 Java 方法时类型不匹配

[英]Type mismatch when call java generic Java method from Scala code

I have a n-quantity of Java classes with one superclass - data model.我有 n 个带有一个超类的 Java 类 - 数据模型。 The list of the classes is input parameter to Scala method in which I want to create resultStreams and have to create call Java generic methods from process method.类列表是 Scala 方法的输入参数,我想在其中创建 resultStreams 并且必须从 process 方法创建调用 Java 通用方法。 Could you write how to resolve it?能写出怎么解决吗? I tried to use [_ <: SpecificRecordBase], [SpecificRecordBase] in the method calling, but had the same result.我尝试在方法调用中使用 [_ <:SpecificRecordBase], [SpecificRecordBase],但结果相同。

Error错误

Error:(146, 88) type mismatch;
 found   : Class[_$3] where type _$3 <: org.apache.avro.specific.SpecificRecordBase
 required: Class[org.apache.avro.specific.SpecificRecordBase]
Note: _$3 <: org.apache.avro.specific.SpecificRecordBase, but Java-defined class Class is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: org.apache.avro.specific.SpecificRecordBase`. (SLS 3.2.10)
                AvroHelper.deSerializeAvroObject(record.value, cl))(TypeInformation.of(cl)))

Scala code斯卡拉代码

object GenerickRunnerStackOverFlow  {
  def process(inputClasses :  List[Class[_ <: SpecificRecordBase]],): Unit = {
    val newStream: DataStream[KafkaSourceType] = env.addSource(....)).uid(...).filter(...)

    val resultStreams = inputClasses .map(
      cl => newStream.map(record =>
                AvroHelper.deSerializeAvroObject(record.value, cl))(TypeInformation.of(cl)))

        ...
  }

    def main(args: Array[String]): Unit = {
        val topicToClasses: List[Class[_ <: SpecificRecordBase]] = List(Types.RECORD_1.getClassType, Types.RECORD_1.getClassType.getClassType)
        process(topicToClasses)

    }
}

Java method spec Java 方法规范

public static <A extends SpecificRecord> A deSerializeAvroObject(byte[] object, Class<A> clazz){ ...}

Model模型

    public class Record1 extends SpecificRecordBase {}
    public class Record2 extends SpecificRecordBase {}
    ...
    public enum Types {
      RECORD_1(Record1.class),
      RECORD_2(Record2.class);
      ....

      private Class<? extends SpecificRecordBase> clazz;
      public Class<? extends SpecificRecordBase> getClassType() {return this.clazz;}
}

Also I have the same message error with Scala addSink method:我也有与 Scala addSink 方法相同的消息错误:

def addSink(sinkFunction : org.apache.flink.streaming.api.functions.sink.SinkFunction[T]) : org.apache.flink.streaming.api.datastream.DataStreamSink[T] = { /* compiled code */ }

I write the wrapper method:我写了包装方法:

def addSinkWithSpecificRecordBase[A <: SpecificRecordBase](
    stream: DataStream[A],
    sink: BucketingSink[A]): DataStreamSink[A] = stream.addSink(sink)

In result of execution:执行结果:

val result = topicToSinkStream.foreach { el =>
  val stream: DataStream[_ <: SpecificRecordBase] = el._2._1
  val sink: BucketingSink[_ <: SpecificRecordBase] = el._2._2
  addSinkWithSpecificRecordBase(stream, sink)
}

There was an error:有一个错误:

Error:(209, 37) type mismatch;
 found   : org.apache.flink.streaming.api.scala.DataStream[_$9] where type _$9 <: org.apache.avro.specific.SpecificRecordBase
 required: org.apache.flink.streaming.api.scala.DataStream[org.apache.avro.specific.SpecificRecordBase]
Note: _$9 <: org.apache.avro.specific.SpecificRecordBase, but class DataStream is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
      addSinkWithSpecificRecordBase(stream, sink)

Where topicToSinkStream is:其中 topicToSinkStream 是:

Map[String, (DataStream[_ <: SpecificRecordBase], BucketingSink[_ <: SpecificRecordBase])]

I also tried to eliminate the SpecificRecordBase in method gemeric description and Add + and - to method parameters description.我还尝试消除方法gemeric 描述中的SpecificRecordBase 和Add + and - to method parameters description。 But there is no result.但是没有结果。

The issue is that the type of AvroHelper.deSerializeAvroObject(record.value, cl) is SpecificRecordBase ( _ <: SpecificRecordBase is only allowed in type parameters , not here).问题是AvroHelper.deSerializeAvroObject(record.value, cl)的类型是SpecificRecordBase_ <: SpecificRecordBase只允许在类型参数中,而不是在这里)。 The fix is to extract a helper function:解决方法是提取一个辅助函数:

def processClass[A <: SpecificRecordBase](cl: Class[A], newStream: DataStream[KafkaSourceType]) = 
  newStream.map(record => AvroHelper.deSerializeAvroObject(record.value, cl))(TypeInformation.of(cl)))

(if you define it locally you can also use newStream without making it an argument) and then (如果您在本地定义它,您也可以使用newStream而不将其作为参数)然后

val resultStreams = inputClasses.map(cl => processClass(cl, newStream))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM