问题
I have a Maven project with Kotlin code hello.kt
which calls Java code JavaFoo.java
which calls Kotlin code KotlinFoo.kt
. hello.kt
also calls KotlinFoo.kt
directly. I'm trying to build this with mvn clean install
using exactly the Maven settings described in kotlinlang's Maven docs.
If hello.kt
doesn't call JavaFoo
(but I leave JavaFoo
in the project) then this builds just fine.
The docs say that the Kotlin compiler should be invoked before the Java compiler, which suggests to me that all Kotlin code needs to compile before any Java code, i.e. with this setup you can call Kotlin from Java but not vice versa. However, the docs describe this setup as just "mixed code applications", not "calling Kotlin from Java".
In other words, this failure seems consistent with what the docs seem to imply but not with what they directly say -- or I'm just misunderstanding something.
I want to call each language from the other. Is there a Maven configuration that will do this, please?
(I looked at various StackExchange questions on mixed code settings and none of the solutions works for me.)
Adding the code as requested: pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.kotlindemo</groupId>
<artifactId>kotlin-demo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>kotlin-demo</name>
<properties>
<kotlin.version>1.1.2-2</kotlin.version>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<main.class>com.example.kotlindemo.HelloKt</main.class>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals> <goal>single</goal> </goals>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/kotlin/hello.kt
:
package com.example.kotlindemo
fun main(args : Array<String>) {
println("Hello, world!")
var kfoo = KotlinFoo()
kfoo.printFooString()
kfoo.fooString = "init2"
kfoo.printFooString()
var foo2 = JavaFoo("abcd")
foo2.printString()
}
src/main/kotlin/KotlinFoo.kt
:
package com.example.kotlindemo
class KotlinFoo {
var fooString = "init"
fun printFooString() {
println(this.fooString)
}
}
src/main/java/JavaFoo.java
:
package com.example.kotlindemo;
class JavaFoo {
private KotlinFoo k;
JavaFoo(String initializer) {
k = new KotlinFoo();
k.setFooString(initializer);
}
void printString() {
this.k.printFooString();
}
}
Error:
[ERROR] .../src/main/kotlin/hello.kt: (12, 14) Unresolved reference: JavaFoo
回答1:
The compilation fails because your Java class is not in a directory that matches its package statement. While Kotlin allows you to put classes in any directories regardless of the package they're in, Java requires you to put each file in a package that corresponds to its directory. This requirement applies to mixed-language projects as well.
To fix the error, move JavaFoo.java
to src/main/java/com/example/kotlindemo
.
回答2:
If you are using maven, you need to add the goal: <goal>addSources</goal>
Like this:
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>addTestSources</goal>
<goal>generateStubs</goal>
<goal>compile</goal>
<goal>testGenerateStubs</goal>
<goal>testCompile</goal>
<goal>removeStubs</goal>
<goal>removeTestStubs</goal>
</goals>
</execution>
</executions>
来源:https://stackoverflow.com/questions/44052965/mixed-kotlin-java-with-maven-unresolved-reference