In my code, it appears convenient to use varargs when implementing a generic method when the type is an array:
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) {...}
}
When I write this, Eclipse shows a warning:
Varargs methods should only override or be overridden by other varargs methods unlike MyCodec.encode(byte...) and Codec.encode(byte[])
Should I just ignore the warning, or is this going to cause some unforeseen problems?
This is an Eclipse-specific warning. It has nothing to do with generics specifically and can be reproduced with this example:
class A {
m(int[] ints) { }
}
class B extends A {
@Override
m(int... ints) { }
}
As the other answers point out, varargs are purely a compile-time feature and there's no difference at runtime. I tried searching for the specific reasoning behind the warning but couldn't turn anything up. Likely it's considered bad practice to alternate method overrides between varargs and non-varargs because it's confusing and arbitrary. But this is in general - your use case seems more reasonable as long as callers are always going to be using a statically-typed MyCodec
instead of coding to interface with a Codec<byte[], char[]>
.
Unfortunately there is no way to suppress this warning - even @SuppressWarnings("all")
won't make it yield. Which is unfortunate considering how obscure of a warning it is. Here's an ancient conversation about this same issue: http://echelog.com/logs/browse/eclipse/1196982000 (scroll to 20:45:02) - proving it's bit people long before you. Seems like an Eclipse bug that it can't be suppressed.
I wrote two test files. Here's the first:
public class Test {
public static void main(String... args) {
System.out.println(java.util.Arrays.toString(args));
}
}
And here's the second:
public class Test {
public static void main(String[] args) {
System.out.println(java.util.Arrays.toString(args));
}
}
(The only difference between these two files is the String[] args
vs String... args
.)
Then, I ran javap -c
on each file to see the disassembly. The contents of the main
method were identical:
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
The only difference was the method header, which was simply the method signature of each method:
public static void main(java.lang.String[]);
public static void main(java.lang.String...);
With this in mind, I would say that it's a safe assumption that nothing bad will happen.
According to the bytecode, no problem.
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
If you make a call using one reference of the interface, the method with the flag ACC_BRIDGE
check (checkcast
) if the type of the argument is the same as is defined in the type parameter (java.lang.ClassCastException
otherwise, but will never happen if you allways provides the type parameter), then run the method implementation.
In another hand, if you compile this with javac, none warning is show.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With