从 Java 访问时,Scala public 变为私有?

Scala public becomes private when accessed from Java?

我对 JavaMaven 非常熟悉,但对 Scala。我正在尝试从 Java 访问 Scala 我似乎无法理解的问题之一如下:

我的问题

AccessScala.java中我尝试访问WithinModule.scala中的一个变量:

package me.parent.jModule;

public class AccessScala{
    public static void main(String[] args){
        WithinModule within = new WithinModule();
        // -- this is like a static variable
        System.out.println(WithinModule.string);
        // -- this is like an instance variable
        System.out.println(within.string);
        // -- this is a getter, as it should be in Java
        System.out.println(within.getString());
    }
}

这个变量should be public

package me.parent.jModule;

class WithinModule{
  val string : String = "this is the local scala string";
}

但是当 运行 mvn clean package 它告诉我这个变量是私有的:

[ERROR] [Error] C:\projectLocation\parent\jModule\src\main\java\me\parent\jModule\AccessScala.java:7: string has private access in me.parent.jModule.WithinModule
[ERROR] [Error] C:\projectLocation\parent\jModule\src\main\java\me\parent\jModule\AccessScala.java:9: string has private access in me.parent.jModule.WithinModule

基本上,是我误解了它应该如何工作,还是我做错了什么?

项目设置

我将项目放在 GitHub 上,并总结了此处可能相关的内容。这些文件是这样组织的

> parent
 | > jModule
 | | > src/main
 | | | > java/me/parent/jModule
 | | | | > AccessScala.java
 | | | > scala/me/parent/jModule
 | | | | > WithinModule.scala
 | | > pom.xml
 | > sModule
 | | > src/scala/me/parent/sModule
 | | | >ExternalModule.scala
 | | > pom.xml
 | > pom.xml

我的 parent pom.xml 主要来自 here。经过一些修改,它最终如下所示。这个确切的设置在另一个项目上工作正常,其中(到目前为止)只有一个案例 Java 使用 class 写在 Scala,但两种语言都有大量代码。测试和所有工作正常,直到我们尝试从 ScalaJava.[=25= 中访问 vals ]

我使用 Maven compilersurefirefailsafe 插件来编译和测试 Java(还没有测试)和 Scala-MavenScalaTest 插件来编译和测试 Scala 代码(也没有测试).它们被配置为首先编译和测试 Scala,然后继续 Java.

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>me</groupId>
    <artifactId>parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.5.1</version>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.scalatest</groupId>
            <artifactId>scalatest_2.13</artifactId>
            <version>3.1.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- stuff for compiling and testing Java during `mvn package` -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M3</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>3.0.0-M3</version>
            </plugin>
            <!-- This is for Scala compilation during `mvn package` -->
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>4.3.1</version>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <!--
            <execution>
              <id>scala-test-compile</id>
              <phase>process-test-resources</phase>
              <goals>
                <goal>testCompile</goal>
              </goals>
            </execution>
            -->
                </executions>
            </plugin>
            <plugin>
                <groupId>org.scalatest</groupId>
                <artifactId>scalatest-maven-plugin</artifactId>
                <version>1.0</version>
                <configuration>
                    <reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
                    <junitxml>.</junitxml>
                    <filereports>WDF TestSuite.txt</filereports>
                </configuration>
                <executions>
                    <execution>
                        <id>test</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>test</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <modules>
        <module>jModule</module>
        <module>sModule</module>
    </modules>
</project>

PS

如有任何建议,我们将不胜感激。正如我提到的,我正试图让 Java 和 Scala 一起工作,我听说这应该很容易,但我让 运行 成为问题,这就是其中之一。

分析 scalac -print 输出我们看到

class WithinModule {
  val string : String = "this is the local scala string"
}

扩展为

  class iw$WithinModule extends Object {
    private[this] val string: String = _;
    <stable> <accessor> def string(): String = iw$WithinModule.this.string;
    def <init>(): $line184.iw$WithinModule = {
      iw$WithinModule.super.<init>();
      iw$WithinModule.this.string = "this is the local scala string";
      ()
    }
  }

我们注意到 def string(): String,因此在 AccessScala.java 中尝试

WithinModule within = new WithinModule();
System.out.println(within.string());