问题
I often find code which uses generics in Java like this:
public static <T extends Object & Interface> foo(T object) {
...
}
Since in Java every class inherites from object class I'm not sure if extends Object
gives a special meaning or is used for special purposes. Can anyone tell me if there is a different background using this or this is implicit given when you take <T extends Interface>
?
回答1:
<T extends Object & Interface>
That Object
is clearly redundant and typically equals to
<T extends Interface>
Note that using Interface
as a class name is highly discouraged.
回答2:
This may be necessary to make your code backwards-compatible on binary level. Suppose that you have the following utility class:
public class Utils {
public static <T> int length(T obj) {
if(obj instanceof CharSequence) {
return ((CharSequence)obj).length();
}
return 0;
}
}
It's published as a library and used in some applications like this:
public class Main {
public static void main(String... args) {
System.out.println(Utils.length("foo"));
}
}
Works fine. However later you decided that it's good to limit your method only to implementations of some interface CharSequence
as for other objects it always returns 0 anyways and seems that nobody uses your method with non-CharSequence parameter. So you change the signature to
public static <T extends CharSequence> int length(T obj) { ... }
Now if you link the Main
class with new version of your library, it will fail with java.lang.NoSuchMethodError
. That's because the erased signature of your method changed. Before it was int length(Object obj)
, but now it's int length(CharSequence obj)
. If you recompile the Main
class, it will work fine, but it's not always possible to recompile all the existing code. Thus the trick could be performed:
public static <T extends Object & CharSequence> int length(T obj) { ... }
Now you're actually limiting the parameter to CharSequence
interface, but the erased signature is back to int length(Object obj)
(the erased type is always the first in the chain of A & B & C & ...
, it's officially documented), so the new version of Utils
class is binary compatible with the old code.
回答3:
As you noted, any T
would implicitly extend Object
anyway. Explicitly defining T extends Object
is completely redundant, and you could (and probably should) remove it, and just define T extends Interface
.
来源:https://stackoverflow.com/questions/32795995/java-generics-special-usage-t-extends-object-interface