Mixed Kotlin + Java with Maven, unresolved reference

狂风中的少年 提交于 2020-01-24 03:11:25

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!