javacは文句:列挙型の実装インタフェース上のシンボルを見つけることができません
質問
私は3つのJavaの型を持っています:
Main.javaます:
import java.util.Arrays;
import java.util.List;
public class Main
{
private Object callFunction()
{
OperationDefinitions func = OperationDefinitions.CONCATENATE;
List<Object> values = Arrays.asList(new Object[] {"ABC", "-", "DEF"});
return func.call (values);
}
public static void main (String[] args)
{
Main main = new Main();
System.out.println (main.callFunction());
}
}
Operation.java
import java.util.List;
public interface Operation
{
abstract Object call(List<Object> params);
}
OperationDefinitions.java
import java.util.List;
enum OperationDefinitions implements Operation
{
CONCATENATE() {
public Object call(List<Object> params)
{
StringBuilder builder = new StringBuilder();
for (Object param : params) builder.append((String)param);
return builder.toString();
}
},
;
}
は(これはほぼ正確に効果的なJavaの第2版で与えられた例である。項目30) 上記のコードはコンパイルされ、Eclipseでうまく動作しますが、Sunのjavacので、私は次のエラーを取得する:
Main.java:12: cannot find symbol
symbol : method call(java.util.List<java.lang.Object>)
location: class OperationDefinitions
return func.call (values);
^
1 error
私はそれがうまくコンパイルreturn func.call(values);
するreturn ((Operation)func).call(values)
からMain.javaのライン12を変更した場合。私は、単一のメインクラスの3つのサブクラスとして一緒に三種類(オペレーション、メインとOperationDefinitions)を置けばさらに、それは同様に罰金コンパイルします。
だから私は私の問題のための回避策を持っていますが、私は不思議を行う、なぜjavacは、ここでキャストが必要ですが、日食はないでしょうか?これは、javacの中またはEclipseのバグですか?
私はSunのjavacの1.5.0_19および1.6.0_16の両方を試してみた。
他のヒント
これは、Sunのjavacのバグかもしれません。 func
はenum
ある(つまりenum
がOperation
を実装した場合でも)とEnum
クラスはメソッドのcall()
を持っていません。この問題を解決するために、私は割り当てを変更することをお勧めします:
Operation func = OperationDefinitions.CONCATENATE;
それはまた、あなたが期待するもの、それを明確にします:操作、ないenum
。 enum
は、すべての可能な操作(必要であれば、コンテナ)を収集するだけの便利な方法です。
これは、バグですが、新しいバージョン(ただし、必要があります)へのアップデートを行うことができない場合...ただ、OperationDefinitions
からintefaceをを削除し、でメソッド...call(...)
を置きます列挙型、このような:
public abstract Object call(List params);
動作するはずです。
私は、これは実際にjavac
のバグである疑いがあります。それはOperationDefinitions
インターフェイスを実装するのでOperation
は間違いなく に、(抽象)メソッド呼び出し(java.util.Listの)を持っています。すべての定数は、このインタフェースの具体的な実装を提供するので、クラス定義は、有効です。
このため、部分的に責任があるかもしれない一つのことは、私の知識へのインタフェースで定義されたすべてのメソッドはパブリックでなければならないということです。あなたが本当にデフォルトのアクセス修飾子とのインタフェースにcall
メソッドを定義した場合、私はそれを拒否するようにコンパイラに期待 - しかし、それはその後、ない場合には、ラインの下の問題を見て私は驚かないだろう。これはタイプミスが、その後大丈夫だったが、それはそのようなものだならば、問題が消える場合は、あなたのコード内でパブリックとして宣言して見てみてください。