不覆盖接口默认实现时的编译失败

时间:2019-10-03 06:44:37

标签: java scala apache-spark-sql maven-compiler-plugin

我正在尝试实现org.apache.spark.sql.Row。接口具有几种方法的默认实现,并且IntelliJ不会抱怨不重写这些方法。 但是,当使用Maven进行构建时,我得到:

FunctionalRow is not abstract and does not override abstract method mkString(java.lang.String,java.lang.String,java.lang.String) in org.apache.spark.sql.Row

下面是该类的实现:

import java.util.List;
import java.util.function.Supplier;

import org.apache.spark.sql.Row;

import scala.collection.JavaConverters;
import scala.collection.Seq;

public class FunctionalRow implements Row {
    protected List<Supplier<Object>> suppliers;

    public FunctionalRow(List<Supplier<Object>> suppliers) {
        this.suppliers = suppliers;
    }

    @Override
    public int length() {
        return suppliers.size();
    }

    @Override
    public Object get(int i) {
        return suppliers.get(i).get();
    }

    @Override
    public Row copy() {
        return this;
    }

    @Override
    public Seq<Object> toSeq() {
        return JavaConverters.asScalaIteratorConverter(suppliers.stream().map(s -> s.get()).iterator()).asScala().toSeq();
    }
}

maven-compiler-plugin设置:

        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
          <executions>
            <execution>
              <id>default-compile</id>
              <phase>compile</phase>
              <goals>
                <goal>compile</goal>
              </goals>
              <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
              </configuration>
            </execution>
            <execution>
              <id>default-testCompile</id>
              <phase>test-compile</phase>
              <goals>
                <goal>testCompile</goal>
              </goals>
              <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
              </configuration>
            </execution>
          </executions>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <encoding>UTF-8</encoding>
          </configuration>
        </plugin>

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

我正在对答案发表评论,以便您可以将此问题标记为已回答。

TL; DR:如果特性是由早于2.12的Scala版本编译的,则无法在Java中对Scala特性使用默认实现。此处使用的Spark版本就是这种情况,因此所有希望都荡然无存。

原因与Scala编译器如何编码特征以使其与JVM(并因此与Java)兼容有关。

在Java 8之前,不允许接口提供默认实现。 Scala特征本质上是具有默认实现的可堆叠接口,必须对其进行编码,使其既没有实现的接口,又提供提供实现的抽象类。有关详细信息,请参见this answer

在Java 8 之后,允许接口提供默认实现,因此Scala可以使用默认实现直接对Java接口进行编码,并直接与Java代码兼容。从Scala 2.12开始,Scala需要Java 8+兼容的JVM,因此具有trait <->接口兼容性。如果Scala代码是由Scala 2.12+编译器编译的,则可以将其特征用作常规Java接口。