7

此方法应采用两个相同类型的对象并随机返回其中一个对象:

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

现在,为什么编译器接受两个具有不同类型的参数?

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

编辑: 现在我知道这两个参数都被隐式向上转换,我想知道为什么编译器调用以下方法时会抱怨:

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

称呼:

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

如果这些 ArrayList 参数也被向上转换为 Object,为什么这次它会给我一个错误?

4

4 回答 4

11

T被推断为Object,并且两个参数都被隐式地向上转换。

因此代码等价于:

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

可能更令人惊讶的是以下编译:

random("string1", 10);

第二个参数被自动装箱为Integer,然后两个参数都被向上转换为Object

于 2012-12-18T21:24:45.040 回答
5

T被推断为 and 的常见超类型StringInteger

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

好吧,没有人需要关心这个。

您可以在参数类型上添加更多约束

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

在您的列表示例中,您需要通配符才能获得类似的效果

public static <T> List<? extends T> randomList(
                                    List<? extends T> l1, List<? extends T> l2)
于 2012-12-18T21:39:48.160 回答
3

知道我知道这两个参数都被隐式向上转换,我想知道为什么编译器在调用以下方法时会抱怨:

因为即使 whenA是 的子类型BList<A>也不是List<B>if A 和 B 不同的子类型。

于 2012-12-19T02:26:21.763 回答
1

因为您没有以安全、通用的方式调用它。尝试

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

你会得到一个编译错误。

或者让编译器推断类型,你也应该得到一个编译错误:

String s = random("string1", new Integer(10));
于 2012-12-18T21:27:32.527 回答