Why does this generic java method accept two objects of different type?

心已入冬 提交于 2019-12-19 08:04:41

问题


This method shall take two objects of the same type and return one of those objects by random:

public static <T> T random(T o1, T o2)
{
   return Math.random() < 0.5 ? o1 : o2;
}

Now, why does the compiler accept two parameters with distinctive types?

random("string1", new Integer(10)); // Compiles without errors

EDIT: Now that I know that both parameters are getting implicitly upcasted, I wonder why the compiler does complain when calling the following method:

public static <T> List<T> randomList(List<T> l1, List<T> l2) {
        return Math.random() < 0.5 ? l1 : l2;
    }

Call:

randomList(new ArrayList<String>(), new ArrayList<Integer>()); // Does not Compile

If those ArrayList Parameters are also getting upcasted to Object, why does it give me an error this time?


回答1:


T is inferred to be Object, and both arguments are getting implicitly upcast.

Thus the code is equivalent to:

Main.<Object>random((Object)"string1", (Object)new Integer(10));

What may be even more surprising is that the following compiles:

random("string1", 10);

The second argument is getting auto-boxed into an Integer, and then both arguments are getting upcast to Object.




回答2:


T is inferred to be the a common super type of String and Integer, which is

Object & Serializable & Comparable<? extends Object & Serializable & Comparable<? extends ... ...

well, nobody needs to care about that.

You can add a little more constraints on the parameter types

public static <T1,T2 extends T1> T1 random(T1 o1, T2 o2)

In your list example, you need wildcards to get the similar effect

public static <T> List<? extends T> randomList(
                                    List<? extends T> l1, List<? extends T> l2)



回答3:


Know that I know that both parameters are getting implicitly upcasted, I wonder why the compiler does complain when calling the following method:

Because even when A is a subtype of B, List<A> is not a subtype of List<B> if A and B are different.




回答4:


Because you don't call it in a safe, genericized way. Try

MyClass.<String>random("string1", new Integer(10));

And you'll get a compilation error.

Or let the compiler infer the type, and you should also get a compilation error:

String s = random("string1", new Integer(10));


来源:https://stackoverflow.com/questions/13941716/why-does-this-generic-java-method-accept-two-objects-of-different-type

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