HI: java中的泛型类型是什么?只是为了减少类强制转换异常?
另外,K表示“键”,V表示“valuse”,E和T怎么样?
对于泛型类,例如: 列表,我理解为列表只能放置String类型的对象,但我不太清楚泛型方法:
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o); // Correct
}
}
上述&gt;中T的含义是什么?任何人都可以给我一个简单的表达吗?
我读了sun的教程,但是我还不明白。所以我希望有人可以在没有太多专业话语的情况下解释它。
答案 0 :(得分:2)
字母E和T分别代表元素和类型,但请注意它们不是由编译器强制执行或类似的。你几乎可以放任何东西,包括完整的单词,但建议你使用单个大写字母,这样可以更好地区分它们(小写单词看起来像变量名,以大写字母开头的单词看起来像类,完整的大写单词看起来像常量)
至于使用方式,请这样考虑。创建数组时,您可以创建Object[]
,String[]
,Integer[]
,SomeClass[]
,它可以准确地告诉您其中的内容。直到引入集合/地图类(List,Set,Map)的泛型有问题,你可以把任何东西放在那里(有些人可能认为这不是问题)。所以现在你可以创建类似于数组的List<String>
,List<Object>
。但是有一些不同之处。例如String[]
扩展Object[]
,但List<String>
不扩展List<Object>
,因此您无法将字符串列表实例放入对象列表变量中。
泛型的优点是你可以在任何类上拥有它们,并且一个类可以有多个泛型参数(如Map<K, V>
)。您可以将其视为给予其他类实例的Class
参数,告诉他们应该接收或返回的方法类型。
是的,关键是编译器可以检查你是否给他们正确的参数类型,这样你就可以避免在运行时出现的ClassCastExceptions。例如,在泛型之前你可以这样做:
String s = "";
List l = new ArrayList();
l.add(s);
Integer i = (Integer)l.get(0); // ClassCastException
但是使用泛型:
String s = "";
List<String> l = new ArrayList<String>();
l.add(s);
Integer i = (Integer)l.get(0); // compiler warning: cannot cast from String to Integer
此外,您可以在示例中的单个方法上使用泛型类型参数(类本身不需要为此设置类型参数)。这告诉编译器该方法必须匹配方法参数和/或返回类型上的type参数的所有实例。在您的示例中,将其称为:
String[] a = new String[1];
List<Integer> l = new ArrayList<Integer>();
fromArrayToCollection(a, l);
将导致编译错误,因为该方法必须接收T[]
和Collection<T>
,T在这里是相同的。但是你给它一个String[]
(所以T这里是String)和一个List<Integer>
(所以T这里是整数,而不是String)。如果l是List<String>
,它会起作用。
另请注意List<T>
扩展Collection<T>
,因为List扩展了Collection,但即使T扩展S(无论T和S是什么),List<T>
也不会扩展List<S>
。
哦,你可以在泛型上使用通配符来指定可替换类型参数的类的限制:
public <T extends SomeClass> void fromArrayToCollection(T[] a, COllection<T> c);
这样,如果你给它SomeClass []或SomeChildClass [](其中SomeChildClass扩展SomeClass),而不是Object []或String [],该方法将起作用。
答案 1 :(得分:1)
T代表Type。实例化泛型类时,必须指定实例中包含的类型。因此,您可以拥有String或MyType或WhateverType的集合,而不是拥有对象集合。
泛型给出类编译时类型的安全性。如果您尝试将错误的数据类型粘贴到通用集合中,您将收到编译器警告。就我个人而言,我更倾向于在一英里之外抓住一个演员例外。此外,与非泛型集合不同,从Generic集合中检索时无需从Object类型强制转换。
答案 2 :(得分:0)
中
static <T> void fromArrayToCollection(T[] a, Collection<T> c)
声明“T”是泛型类型而不是某个类的名称。否则,编译器将查找名为“T”的类。