Java 未重写接口默认实现时编译失败

Java 未重写接口默认实现时编译失败,java,scala,apache-spark-sql,maven-compiler-plugin,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 下面是类的

我正在尝试实现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();
    }
}
import java.util.List;
导入java.util.function.Supplier;
导入org.apache.spark.sql.Row;
导入scala.collection.JavaConverters;
导入scala.collection.Seq;
公共类FunctionalRow实现行{
受保护的供应商名单;
公职人员流动(供应商名单){
这意味着供应商=供应商;
}
@凌驾
公共整数长度(){
返回供应商。大小();
}
@凌驾
公共对象get(int i){
返回供应商.get(i).get();
}
@凌驾
公用行副本(){
归还这个;
}
@凌驾
公开序号toSeq(){
返回JavaConverters.asscalateratorconverter(suppliers.stream().map(s->s.get()).iterator()).asScala().toSeq();
}
}
maven编译器插件设置:

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

maven编译器插件
3.8.0
默认编译
编译
编译
1.8
1.8
UTF-8
默认测试编译
测试编译
测试编译
1.8
1.8
UTF-8
1.8
1.8
UTF-8

任何帮助都将不胜感激

我正在把我的评论变成一个答案,这样你就可以把这个问题标记为已回答

TL;DR:如果Scala traits是由早于2.12的Scala版本编译的,则不能在Java中使用默认的Scala traits实现。这里使用的Spark版本就是这种情况,因此失去了所有希望。

原因与Scala编译器如何编码特性以与JVM兼容(因此也与Java兼容)有关

在Java8之前,接口不允许提供默认实现。Scala traits基本上是具有默认实现的可堆叠接口,必须进行编码,它既有一个没有实现的接口,也有一个提供实现的抽象类。有关详细信息,请参阅


在Java8之后,接口被允许提供默认实现,因此Scala可以直接将默认实现的特性编码到Java接口,并与Java代码直接兼容。自Scala 2.12以来,Scala需要一个与Java 8+兼容的JVM,因此带来了traitinterface兼容性。如果Scala代码是由Scala 2.12+编译器编译的,您可以将它的特性用作普通Java接口。

我将我的评论作为答案,这样您就可以将这个问题标记为已回答

TL;DR:如果Scala traits是由早于2.12的Scala版本编译的,则不能在Java中使用默认的Scala traits实现。这里使用的Spark版本就是这种情况,因此失去了所有希望。

原因与Scala编译器如何编码特性以与JVM兼容(因此也与Java兼容)有关

在Java8之前,接口不允许提供默认实现。Scala traits基本上是具有默认实现的可堆叠接口,必须进行编码,它既有一个没有实现的接口,也有一个提供实现的抽象类。有关详细信息,请参阅


在Java8之后,接口被允许提供默认实现,因此Scala可以直接将默认实现的特性编码到Java接口,并与Java代码直接兼容。自Scala 2.12以来,Scala需要一个与Java 8+兼容的JVM,因此带来了traitinterface兼容性。如果Scala代码是由Scala 2.12+编译器编译的,您可以使用它的特性作为普通Java接口。

也许不能这样做?您使用的Spark版本是使用Scala 2.12或更高版本编译的吗?使用Scala 2.12,traits可以直接编译为Java接口。这是因为Java 8在接口中引入了默认实现,所以Scala 2.12(需要Java 8+)可以转换为接口,而不需要您在链接的答案中引用的复杂机制。我不是Java互操作专家,但是Java应该看到
mkString
的默认实现,如果它确实存在的话。所以2.12不是一个选项。。。升级spark将完全超出我的任务范围,所以我现在不得不接受这个限制。但是很高兴知道,谢谢!也许这是不可能的?您使用的Spark版本是使用Scala 2.12或更高版本编译的吗?使用Scala 2.12,traits可以直接编译为Java接口。这是因为Java 8在接口中引入了默认实现,所以Scala 2.12(需要Java 8+)可以转换为接口,而不需要您在链接的答案中引用的复杂机制。我不是Java互操作专家,但是Java应该看到
mkString
的默认实现,如果它确实存在的话。所以2.12不是一个选项。。。升级spark将完全超出我的任务范围,所以我现在不得不接受这个限制。但是很高兴知道,谢谢!