Scala public becomes private when accessed from Java?

Sonke Wohler :

I am quite familiar with Java and Maven, but not at all with Scala. I am trying to access Scala from Java and one of the problems I can't seem to understand is the following:

My Question

In AccessScala.java I try to access a variable in 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());
    }
}

This variable should be public

package me.parent.jModule;

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

But when running mvn clean package it tells me this variable is private:

[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

Basically, am I misunderstanding how this should work, or am I doing something wrong?

Project Setup

I put the project up on GitHub, with a summary of what may be relevant here. The files are organised like so

> 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

I took my parent pom.xml mostly from here. With some modifications it ended up like below. This exact setup works fine on another project where there was (so far) only one case where Java was making use of a class written in Scala, but plenty of code in both languages. Testing and all worked fine, until we tried to access vals from Scala within Java.

I use the Maven compiler, surefire and failsafe plugins to compile and test Java (no tests yet) and the Scala-Maven and ScalaTest plugins to compile and test Scala code (also no tests yet). They are configured to compile and test Scala first, then move on to 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

Any suggestions what is going on would be appreciated. As I mentioned I'm trying to make Java and Scala work together, which I hear should be quite easy, but I keep running into issues, this is one of them.

Mario Galic :

Analysing scalac -print output we see that

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

expands to something like

  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";
      ()
    }
  }

where we note def string(): String, therefore in AccessScala.java try

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

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=417499&siteId=1