Reputation: 177
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?
Upvotes: 8
Views: 2767
Reputation: 122489
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.
Upvotes: 3
Reputation: 45443
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)
Upvotes: 5
Reputation: 500673
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
.
Upvotes: 11
Reputation: 691943
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));
Upvotes: 1