java – 泛型方法参数行为

考虑下面的通用方法程序:

class GenericTest {
    int i;
}
public class GenericMethod {

    public <T> List<T> addList(T t, T t1) {
        List<T> list=new ArrayList<T>();
        list.add(t);
        list.add(t1);
        return list;
    }
    public <T> List<T> addList(T t, T t1, List<T> l) {
        List<T> list=new ArrayList<T>();
        list.add(t);
        list.add(t1);
        list.addAll(l);
        return list;
    }
    public static void main(String[] args) {
        GenericMethod gm=new GenericMethod();
        List l=gm.addList(new Integer(42), "java");           //Line 21
        System.out.println(l);
        List<Object> list = new ArrayList<Object>();
        list.add(false);
        List l2 = gm.addList("java", new Integer(42), list);     //Line 25
        System.out.println(l2);
        GenericTest gt = new GenericTest();
        List l3 = gm.addList("java", gt);          //Line 28
        System.out.println(l3);
        List l4 = gm.addList(gm, gt);              //Line 30
        System.out.println(l4);
        List lst = new ArrayList();
        lst.add(new Object());
        List l5 = gm.addList("java", new Integer(42), lst);    //Line 34
        System.out.println(l5);
        System.out.println(l5.get(0));
    }
}

通过参考链接Java Generics – Confusing behavior,我推断,

在第21行,因为该方法是使用String和Integer调用的,所以它使用Object for T调用方法.对于第25行也是如此,因为List也有类型Object,它使用Object for T调用方法.使用其他类型的Calling List将产生错误.我的推论是否正确?

我无法想到的是

1)传递String和类时的第28行,

2)当两个不同的班级通过时,第30行,

3)当没有类型声明的List作为参数传递时的第34行.

任何人都可以分享他们的知识来清除我的理解任何帮助,将不胜感激!谢谢!

最佳答案

Calling List with other type will produce an error. Is my inference correct?

是;你无法传递List< String>例如,那里.通常,第二个addList方法的意图是错误的.正确的签名是这样的:

public <T> List<T> addList(T t1, T t2, List<? extends T> list)

请注意?扩展语法.如果从列表中读取所有内容,则没有理由不添加它. T的某个特定子类型的列表保证包含Ts.这有什么不同的原因:如果你想添加到这个列表怎么办?假设T是Number,你传入一个Integer列表.双是一个数字.使用List< T>列表,您可以调用list.add(5.0),它将编译并运行,将双精度放入您的整数列表.使用List<?扩展T&gt ;,添加调用始终是编译器错误(除非您尝试添加null,这将起作用).对于阅读,你得到一个T out,无论你是否打电话给列表<?延伸T>或者列表< T>,没关系.

1) Line 28 when String and class is passed,

不,您正在传递String类型的实例和GenericTest类型的实例. String和GenericTest一样是一个类.字符串并不特别.这与第21行中的调用完全相同:您传递了2个表达式;对象类型X之一和对象类型Y中的另一个.因此,T被推断为2个传递实例之间最特定的共享类型(可能是所谓的lub类型:一组类型).在第21行的情况下,Integer和String最具体的共享类型只是Object(技术上,实际上是它的lub类型Object& Serializable,但这里大多数并不重要).在第28行中,它是String和GenericTest之间最具体的共享类型,它仍然是Object,没有区别.

2) Line 30 when two different class is passed,

往上看;恰恰相同的情况. GenericTest和GenericMethod之间最具体的共享类型是Object.

3) Line 34 when List declared without type is passed as argument.

第34行中的表达式lst是’raw’类型ArrayList.当你使用原始类型时,会发生两件事:[1]编译器会警告你你正在使用原始类型,并且[2]几乎所有泛型测试和检查都禁用任何涉及任何原始类型的调用,因此,编译器只会让这种情况发生.

请记住,泛型是编译器想象力的一个虚构.他们的观点是编译器告诉您代码已损坏.就这样.

点赞