4

現在、Ant ビルドの既存の Java プロジェクトがあり、混合ソース (Java と Scala) でビルドするようにセットアップしようとしています。

私は次のように定義されたJavaインターフェースを持っています-public interface One<T extends Two<? super T>>

Ant ビルドから scalac を実行すると、次のエラーが発生します。

エラー: 型 T に関する不正な循環参照です。

プロジェクトで Scala と Java クラスを相互に依存させたいので、Ant ビルドで javac を実行する前に、最初に scalac タスクを実行します。私の scalac ブロックは次のようになります。

<scalac srcdir="${src.path}" destdir="${build.classes}" encoding="UTF-8" >
        <classpath refid="compile.classpath" />
        <include name="**/*.scala"/>
        <include name="**/*.java"/>
</scalac> 

これを回避する方法はありますか?Java コードを使用する他のコードが山ほどあるため、Java コードを変更することはできません。

Java 7 と Scala 2.11.5 を使用しています


これが私の最後に見えるものです:

com.arif.One.java

package com.arif.java;
public interface One<T extends One<? super T>> {
    void test1();
}

com.arif.Two.java

package com.arif.java;
public class Two implements One<Two> {
    @Override
    public void test1() {
    } 
}

com.arif.scala.Main.scala

package com.arif.scala
import com.arif.java.Two

object Main {
  def main(args:Array[String]) {
    var b:Two = null
  } 
}

build.xml

<property name="scala.home" value="/Users/arif/software/scala/scala-2.11.5"/>
<property name="build.classes" value="./build/classes"/>

<property name="src.path" value="src"/>
<property name="javac.target" value="1.7"/>
<property name="compile.debug" value="true" />
<property name="compile.deprecation" value="false" />
<property name="compile.optimize" value="false" />

<path id="compile.classpath">
    <fileset dir="${scala.home}/lib" includes="*.jar" />
</path>

<path id="scala.classpath">
    <pathelement location="${scala.home}/lib/scala-compiler.jar" />
    <pathelement location="${scala.home}/lib/scala-library.jar" />
    <pathelement location="${scala.home}/lib/scala-reflect.jar" />
</path>

<target name="init">
    <taskdef resource="scala/tools/ant/antlib.xml">
        <classpath refid="scala.classpath" />
    </taskdef>
</target>

<target name="build" description="build" depends="init">
    <scalac srcdir="${src.path}" destdir="${build.classes}" encoding="UTF-8" >
        <classpath refid="compile.classpath" />
        <include name="**/*.scala"/>
        <include name="**/*.java"/>
    </scalac>
    <javac srcdir="${src.path}" destdir="${build.classes}" memoryinitialsize="512m" target="${javac.target}" source="${javac.target}" 
        memorymaximumsize="1024m" nowarn="true" debug="${compile.debug}" deprecation="${compile.deprecation}" 
        optimize="${compile.optimize}" fork="true" encoding="iso-8859-1" includeantruntime="false">
        <classpath refid="compile.classpath" />
    </javac>
</target>

プロジェクトルートのコマンドラインから-「antビルド」を実行すると、次のようになります-

[scalac] Compiling 1 scala and 2 java source files to /Users/arif/rbc/scala-java/build/classes
[scalac] /Users/arif/rbc/scala-java/src/com/arif/java/One.java:3: error: illegal cyclic reference involving type T
[scalac] public interface One<T extends One<? super T>> {
[scalac]                                    ^
[scalac] one error found
4

2 に答える 2

1

scalaコードでそのようなことをすると仮定します(javaコードはscalacでうまくコンパイルされるため):

scala> class OneImpl[T <: Two[_ >: T]] extends One[T]
<console>:15: error: illegal cyclic reference involving type T
   class OneImpl[T <: Two[_ >: T]] extends One[T]

実際には、Java コード (および Ant 自体) とは無関係にエラーが発生します。次のように変更することをお勧めします。

scala> class OneImpl[Z >: T, T <: Two[Z]] extends One[T] 
defined class OneImpl

とにかく、Scala は循環参照をサポートしていません。次の方法で回避することもできます (ここで本当に存在型が必要な場合)。

scala> class OneImpl[Z >: T, T <: Two[Z], K <: Two[_ >: Z]](implicit  ev: K =:= T) extends One[T]
defined class OneImpl

http://www.scala-lang.org/old/node/6358を参照してください。

を更新しました。scalac SI-4744に問題があります。すべてのバージョンに影響するわけではないため、最初から見つかりませんでした。javac解決策 (回避策) は、このインターフェイスのみを単独でコンパイルすることです。

javac One.java

または、アリの場合は次のようになります。

<target name="build" description="build" depends="init">
    <javac srcdir="${src.path}" destdir="${build.classes}" encoding="UTF-8">
        <classpath refid="compile.classpath" />
        <include name="**/One.java"/>
    </javac> 
    <scalac srcdir="${src.path}" destdir="${build.classes}" encoding="UTF-8" >
        <classpath refid="compile.classpath" />
        <include name="**/*.scala"/>
        <include name="**/*.java"/>
        <exclude name="**/One.java"/>
    </scalac>
    <javac>...</javac>
</target>
于 2015-01-27T01:20:03.087 に答える