Java Generics: Special usage <T extends Object & Interface>

孤街浪徒 提交于 2020-12-09 06:33:08

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!