web-dev-qa-db-ja.com

javacエラー:ジェネリックスを使用した変換不可能な型?

他にもいくつかのSO EclipseのコンパイラでOKをコンパイルするジェネリックについて話しているがjavacではない質問があります(つまり Java:ジェネリックはEclipseとjavacで異なる処理をしましたGenericsはEclipseでコンパイルおよび実行されますが、javac )ではコンパイルされません。ただし、これは少し異なるように見えます。

enumクラスがあります:

public class LogEvent {
   public enum Type {
       // ... values here ...
   }
   ...
}

Enumから派生したタイプの任意のオブジェクトを取り込むメソッドを持つ別のクラスがあります。

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{
    if (code instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)code;
    ...

これはEclipseで正常に機能しますが、antでクリーンビルドを実行すると、1つはinstanceof行で、もう1つはキャスト行でエラーが発生します。

443: inconvertible types
    [javac] found   : E
    [javac] required: mypackage.LogEvent.Type
    [javac]         if (code instanceof LogEvent.Type)
    [javac]             ^

445: inconvertible types
    [javac] found   : E
    [javac] required: com.dekaresearch.tools.espdf.LogEvent.Type
    [javac]             LogEvent.Type scode = (LogEvent.Type)code;
    [javac]                                                  ^

なぜこれが発生するのですか?また、正しくコンパイルされるようにこの問題を回避するにはどうすればよいですか?

23
Jason S

なぜそれが起こっているのかわかりませんが、回避策は簡単です:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{
    Object tmp = code;
    if (tmp instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)tmp;
    ...

それは醜いですが、それは機能します...

32
Jon Skeet

おそらく、EをEnum <E>を拡張するものとして宣言したためです。完全に理解しているとは言えませんが、タイプのセットが何らかの理由でLogEvent.Typeを含めることができないサブセットに制限されているようです。あるいは、コンパイラのバグかもしれません。誰かがそれをより明確に説明できれば幸いですが、あなたができることは次のとおりです。

public <E extends Enum<?>> void postEvent(E code) 
{
    if (code instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)code;
        ...
    }
    ...

これは機能し、オブジェクトにキャストするよりもエレガントです。

8
Sergei Tachenov

同様の問題が発生し、jdk1.6.0_16からjdk1.6.0_23にアップグレードしたところ、コードを変更せずに解消されました。

4
WW.

instanceofを使用するには、両方のオペランドが同じクラス/インターフェースを継承/実装する必要があります。
EをLogEvent.Typeにキャストすることはできません

あなたの完全な方法がどのように見えるかはわかりませんが、これはジェネリックではなくインターフェースを使用することで問題を解決するはずです。

public interface EventType { }
public class LogEvent  {
    public enum Type implements EventType {}
}

public void postEvent(Context context, EventType code, Object additionalData) {
    if(code instanceof LogEvent.Type) {
    }
}
0
jonescb