请考虑以下通用方法程序:
watch :{
todos:{
handler : function (){
localStorage.todos = JSON.stringify(this.todos);
}
},
deep : true,
},
通过参考链接Java Generics - Confusing behavior可以推断出这一点,
在第21行中,因为同时使用String和Integer调用了该方法,所以它用T的Object调用该方法。第25行也是如此,因为List的类型也为Object,它用Object的方法调用T的方法。其他类型将产生错误。我的推论正确吗?
我想不到的是关于
1)第28行,当传递字符串和类时,
2)第30行,当通过了两个不同的类时,
3)第34行,当将声明为无类型的List传递为参数时。
任何人都可以分享他们的知识以清除我的理解。任何帮助,将不胜感激!谢谢!
答案 0 :(得分:1)
其他类型的呼叫清单将产生错误。我的推论正确吗?
是;例如,您不能在此处传递List<String>
。通常,第二个addList方法的意图是错误的。正确的签名是这样的:
public <T> List<T> addList(T t1, T t2, List<? extends T> list)
请注意? extends
语法。如果您从列表中读取了所有内容,则没有理由不添加它。 T的某些特定子类型的列表保证包含Ts。根本就存在差异的原因:如果您想添加此列表怎么办?假设T为Number
,您传入了Integer
的列表。双是一个数字。使用List<T> list
,您可以调用list.add(5.0)
,它将编译并运行,将双精度数放入整数列表中。使用List<? extends T>
时,add调用始终是编译器错误(除非您尝试添加null
会起作用)。为了阅读,您会得到T
的信息,无论您是在get
还是List<? extends T>
上调用List<T>
,都没关系。
1)第28行,当传递字符串和类时,
否,您要传递String类型的实例和GenericTest类型的实例。字符串与GenericTest一样是一个类。字符串不是特殊的。这与第21行中的调用完全相同:您要传递2个表达式;一个对象类型X,另一个对象类型Y。因此,推断T
是两个传递的实例之间最特定的共享类型(可能是所谓的lub类型:一组类型)。在第21行的情况下,Integer
和String
最特定的共享类型就是Object
(从技术上讲,实际上是lub类型Object & Serializable
,但大多数情况下不是)无关紧要)。在第28行中,它是String
和GenericTest
之间最具体的共享类型,仍然是Object
,没有区别。
2)第30行,当通过了两个不同的类时,
见上文;完全一样的情况。 GenericTest
和GenericMethod
之间最具体的共享类型是Object
。
3)第34行,当将声明为无类型的List传递为参数时。
第34行中的表达式lst
是“原始”类型ArrayList
。当您使用原始类型时,会发生两件事:[1]编译器会警告您您正在使用原始类型,[2]对于涉及任何原始类型的任何调用,几乎所有泛型测试和检查都被禁用,因此,编译器只会让这种情况发生。
请记住,泛型是编译器想象力的体现。他们的意思是让编译器告诉您代码已损坏。就是这样。
答案 1 :(得分:0)
通常,应尽量避免在没有类型参数的情况下声明List
。即使您必须执行List<Object>
,也更加清楚。 (对您和编译器而言)
第25行将不会使用String
,Integer
和List<String>
进行编译,因为传递List<String>
会特别使编译器承担<T>
是String
。
List l2 = gm.addList("java", new Integer(42), new ArrayList<Object>()); // compiles
List l2 = gm.addList("java", new Integer(42), new ArrayList<String>()); // does not compile
您可以将addList
的声明更改为:
public <T> List<T> addList(T t, T t1, List<? extends T> l) {
然后两个示例都将编译。 List
参数上的类型参数不再固定为严格的T
,而是固定为T
或T
的超类型。编译器认为类型参数为Object
,因为Object
是String
(和其他参数)的超类型,因此代码可以编译。
第28行,第30行和第34行返回List<Object>
。可以在参数之间共享的唯一通用类型T
是Object
,因此编译器推断T
是Object
。
就运行时的JVM而言,由于type erasure而没有类型参数,它们都只是List
。类型参数在运行时不存在。