13

私のコードでは、型が配列の場合にジェネリック メソッドを実装するときに varargs を使用すると便利なようです。

public interface Codec<D,E> {
  E encode(D decoded);
  D decode(E encoded);
}

public class MyCodec implements Codec<byte[], char[]> {
  @Override char[] encode(byte... decoded) {...}
  @Override byte[] decode(char... encoded) {...}
}

これを書くと、Eclipse は次の警告を表示します。

Varargs メソッドは、 MyCodec.encode(byte...) や Codec.encode(byte[]) とは異なり、他の varargs メソッドによってのみオーバーライドされるか、オーバーライドされる必要があります。

警告を無視する必要がありますか?それとも、予期しない問題が発生する可能性がありますか?

4

3 に答える 3

9

これは Eclipse 固有の警告です。特にジェネリックとは何の関係もなく、次の例で再現できます。

class A {
    m(int[] ints) { }
}

class B extends A {
    @Override
    m(int... ints) { }
}

他の回答が指摘しているように、varargs は純粋にコンパイル時の機能であり、実行時に違いはありません。警告の背後にある特定の理由を検索しようとしましたが、何も見つかりませんでした。おそらく、可変引数と非可変引数の間でメソッドのオーバーライドを交互に行うのは、紛らわしく恣意的であるため、悪い習慣と見なされます。しかし、これは一般的なことです - 呼び出しMyCodec元がCodec<byte[], char[]>.

残念ながら、この警告を抑制する方法はありませ@SuppressWarnings("all")ん。警告がどれほどあいまいであるかを考えると、これは残念です。これは、この同じ問題に関する昔からの会話です: http://echelog.com/logs/browse/eclipse/1196982000 (20:45:02 までスクロール) - それは、あなたよりずっと前に人々に噛み付いていたことを証明しています。抑制できないEclipseのバグのようです。

于 2013-06-07T04:20:27.510 に答える
4

2 つのテスト ファイルを作成しました。最初は次のとおりです。

public class Test {
    public static void main(String... args) {
        System.out.println(java.util.Arrays.toString(args));
    }
}

そして、これが2番目です:

public class Test {
    public static void main(String[] args) {
        System.out.println(java.util.Arrays.toString(args));
    }
}

(これら 2 つのファイルの唯一の違いは、String[] argsvsString... argsです。)

次に、javap -c各ファイルを実行して逆アセンブリを確認しました。メソッドの内容mainは同じでした:

Code:
   0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
   3: aload_0       
   4: invokestatic  #3                  // Method java/util/Arrays.toString:([Ljava/lang/Object;)Ljava/lang/String;
   7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
  10: return    

唯一の違いは、各メソッドのメソッド シグネチャであるメソッド ヘッダーでした。

  • public static void main(java.lang.String[]);
  • public static void main(java.lang.String...);

これを念頭に置いて、悪いことは何も起こらないというのは安全な仮定だと言えます。

于 2013-06-07T00:55:16.733 に答える
1

bytecodeによると、問題ありません。

public byte[] encode(char...);
  flags: ACC_PUBLIC, ACC_VARARGS

  LineNumberTable:
    line 4: 0
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
           0       2     0  this   LMyEncoder;
           0       2     1  args   [C          // char[]
  Code:
    stack=1, locals=2, args_size=2
       0: aconst_null   
       1: areturn                              // return null;
    LineNumberTable:
      line 4: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature
             0       2     0  this   LMyEncoder;
             0       2     1  args   [C

public java.lang.Object encode(java.lang.Object);
  flags: ACC_PUBLIC, ACC_BRIDGE, ACC_VARARGS, ACC_SYNTHETIC

  LineNumberTable:
    line 1: 0
  LocalVariableTable:
    Start  Length  Slot  Name   Signature
  Code:
    stack=2, locals=2, args_size=2
       0: aload_0       
       1: aload_1       
       2: checkcast     #27          // class "[C"            -> char[]
       5: invokevirtual #28          // Method encode:([C)[B  -> return byte[]
       8: areturn       
    LineNumberTable:
      line 1: 0
    LocalVariableTable:
      Start  Length  Slot  Name   Signature

インターフェイスの 1 つの参照を使用して呼び出しを行う場合、フラグを持つメソッドは、引数の型が型パラメーターで定義されているものと同じかどうACC_BRIDGEか ( ) をチェックします (そうでない場合は、型パラメーターを常に提供する場合は発生しません)。)、次にメソッドの実装を実行します。checkcastjava.lang.ClassCastException

一方、これを javac でコンパイルすると、警告は表示されません。

于 2013-06-07T01:00:47.473 に答える