如何在Scala代码中编译Java record?

4

我目前正在使用Scala和Java编写一个项目。我们想要将一些Scala代码重写为Java代码。所以当我开始重写我的代码时,我遇到了这个问题。

CountryResponse.java:5: illegal start of type declaration

似乎Scala不能编译JDK 16引入的Java记录。我进行了一些研究,发现只有在GitHub上这个讨论。是否有人能提供任何解决方法来编译Java的记录?
我尝试将Scala版本从2.12.2升级到2.13.6,但问题并没有得到解决。
我们使用Java 16、Scala 2.12.2和Gradle 7.0.1,也使用Gradle的Scala和Java插件。
这里还有我的Gradle配置,用于编译两个源文件。
compileScala {
    sourceCompatibility("16")
    targetCompatibility("16")
}

sourceSets {
    main {
        java {
            srcDirs = []
        }
        scala {
            srcDirs = ['src/main/scala', 'src/main/java']
        }
    }
}

编辑:更新讨论链接


Scala本身不编译任何东西。您的构建工具(在这种情况下是gradle)编译包含Java、Scala和Kotlin代码的项目。这个错误——CountryResponse.java:5: illegal start of type declaration与Scala无关,而与gradle有关。您需要正确配置gradle项目以能够编译Java 16代码。 - sarveshseri
你的Java源代码版本相关配置在哪里?另外,系统jdk版本是什么?如果不是Java 16(或更高版本),那么无论你用gradle做什么,jdk都无法编译它。此外,为了使你的Scala代码在Java 16下工作,Scala 2.13的兼容版本是2.13.5,Scala 2.12的兼容版本是2.12.14。 - sarveshseri
1
为什么在Scala的srcDirs中有'src/main/java'?如果您依赖Gradle Scala插件来处理Java 16文件,那么可以从Java的srcDirs中删除它。 - sarveshseri
是的,但是你只需要在Scala srcDir中放置'src/main/java',而不是两个地方都放。 - sarveshseri
是的,gradlew 使用的确切版本来自 build.gradle。https://dev59.com/EaLia4cB1Zd3GeqPhVV9 - NikMashei
显示剩余4条评论
1个回答

4
我测试了一个包含Scala和Java 16源代码的项目。Scala和Java源代码彼此依赖。
如果你的Java和Scala源代码相互依赖,那么你需要将这些源代码放在公共文件夹下。比如说main/jvm
你可以将所有的Java records放在main/java中。只要你的records没有依赖于Scala代码,这将是有效的。否则,你将不得不将其拆分为多个模块,并根据依赖图进行微观管理。
Gradle版本是7.1,这个项目可以成功构建并运行(ScalaMain和JavaMain)。
build.gradle
plugins {
    id 'java'
    id 'scala'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

compileScala {
    sourceCompatibility("16")
    targetCompatibility("16")
}

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java']
        }
        scala {
            srcDirs = ['src/main/jvm']
        }
    }
}

dependencies {
    implementation 'org.scala-lang:scala-library:2.13.6'
}

main/java/TestJavaRecord.java

public record TestJavaRecord(int i) {}

main/jvm/TestScalaClass.scala

class TestScalaClass(val i: Int, val testJavaRecord: TestJavaRecord) {}

main/jvm/TestJavaClass.java

public class TestJavaClass {
    public int i;
    public TestScalaClass testScalaClass;

    public TestJavaClass(int i, TestScalaClass testScalaClass) {
        this.i = i;
        this.testScalaClass = testScalaClass;
    }
}

main/jvm/ScalaMain.scala

object ScalaMain extends App {

  val testJavaRecord = new TestJavaRecord(5)

  val testScalaClass = new TestScalaClass(5, testJavaRecord)

  val testJavaClass = new TestJavaClass(5, testScalaClass)

  println(testJavaRecord.i)

  println(testScalaClass.testJavaRecord.i)

  println(testJavaClass.testScalaClass.testJavaRecord.i)

}

main/jvm/JavaMain.java

public class JavaMain {

    public static void main(String[] args) {
        TestJavaRecord testJavaRecord = new TestJavaRecord(5);

        TestScalaClass testScalaClass = new TestScalaClass(5, testJavaRecord);

        TestJavaClass testJavaClass = new TestJavaClass(5, testScalaClass);

        System.out.println(testJavaRecord.i());

        System.out.println(testScalaClass.testJavaRecord().i());

        System.out.println(testJavaClass.testScalaClass.testJavaRecord().i());
    }
}

如果Java代码也依赖于Scala代码,我该如何配置sourceSets? - NikMashei
3
那么这是一个棘手的情况。Java 16对于record的支持已在https://github.com/scala/scala/pull/9551中添加,但我认为任何发布版本都还没有包含它。 - sarveshseri
是的,这正是我的情况,看起来还没有解决方法,真是遗憾。无论如何,非常感谢您的帮助和时间! - NikMashei
@Zogger 编辑了 Scala 和 Java 代码相互依赖的情况。唯一的例外是,任何 record 都不能依赖于任何 Scala 代码。 - sarveshseri
这很棘手,我已经把所有的Scala代码放在了src/main/scala目录下,Java代码放在了src/main/java目录下。当我将Java源设置为src/main/java,Scala源设置为src/main/scala时,Gradle编译失败了,因为编译器找不到Scala类的源代码... 我真的不知道出了什么问题。 - NikMashei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接