不覆盖接口默认实现时编译失败
Compilation failure when not overriding interface default implementation
我正在尝试实施 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
下面是 class 实现:
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>
如有任何帮助,我们将不胜感激!
我正在将我的评论变成一个答案,因此您可以将此问题标记为已回答。
TL;DR:如果特征是由早于 2.12 的 Scala 版本编译的,则不能在 Java 中使用 Scala 特征的默认实现。这里用的Spark版本就是这样,希望破灭
原因与 Scala 编译器如何编码特征以与 JVM 兼容(因此与 Java)有关。
在 Java8 之前,不允许接口提供默认实现。 Scala 特征,基本上是具有默认实现的可堆叠接口,必须进行编码,既有没有实现的接口,又有提供实现的抽象 class。有关详细信息,请参阅 this answer。
在Java8之后,允许接口提供默认实现,因此Scala可以将具有默认实现的特征直接编码到Java接口,并且直接兼容 Java 代码。从 Scala 2.12 开始,Scala 需要 Java 8+ 兼容的 JVM,因此带来了 trait<->interface 兼容性。如果 Scala 代码已由 Scala 2.12+ 编译器编译,您可以将其特性用作普通 Java 接口。
我正在尝试实施 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
下面是 class 实现:
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>
如有任何帮助,我们将不胜感激!
我正在将我的评论变成一个答案,因此您可以将此问题标记为已回答。
TL;DR:如果特征是由早于 2.12 的 Scala 版本编译的,则不能在 Java 中使用 Scala 特征的默认实现。这里用的Spark版本就是这样,希望破灭
原因与 Scala 编译器如何编码特征以与 JVM 兼容(因此与 Java)有关。
在 Java8 之前,不允许接口提供默认实现。 Scala 特征,基本上是具有默认实现的可堆叠接口,必须进行编码,既有没有实现的接口,又有提供实现的抽象 class。有关详细信息,请参阅 this answer。
在Java8之后,允许接口提供默认实现,因此Scala可以将具有默认实现的特征直接编码到Java接口,并且直接兼容 Java 代码。从 Scala 2.12 开始,Scala 需要 Java 8+ 兼容的 JVM,因此带来了 trait<->interface 兼容性。如果 Scala 代码已由 Scala 2.12+ 编译器编译,您可以将其特性用作普通 Java 接口。