java泛型指导手册(part1),指导手册part1
index
1.大致了解一下
从java5开始,泛型就被加入了java。泛型的意义在于:在你操作object之前,提供了一种指定特定类型为更加通用目的的类或方法的手段。听起来很抽象吧?来点例子看看。
注:泛型当然可以用在不是collection的其他类上,但是呢,用collection来展示泛型的基本概念是很好的。
泛型的例子
List这个接口代表一列表object实例,这意味着我们可以在List里放任何Object,比如:
List list = new ArrayList();
list.add(new Integer(2));
list.add("a String");
因为任何object都可能被加入进来,所以你不得不进行类型转换。比如:
Integer integer = (Integer) list.get(0);
String string = (String) list.get(1);
很经常的一个情况是,你在一个List里仅添加一种类型数据进去,比如String或其他东西,而不是像我在上面做的一样,把integer和String混在一起。
于是,你使用泛型这一特性,可以限制放在List里的object。除此之外,你省去了类型转换的烦恼。看一下用泛型的真正例子:
List strings = new ArrayList();
strings.add("a String");
String aString = strings.get(0);
牛逼吧?
java7里的类型猜测
泛型特性在java7里做了升级。从7开始,java编译器可以从你赋值给的那个变量的信息知道collection的类型,这里是java7里的泛型例子:
List strings = new ArrayList<>();
注意看,ArrayList的泛型类型已经被省略了,仅有<>留了下来。有时候,这东西也叫做菱形操作符。当你写一个菱形操作符作为一个泛型类型,java的编译器会假设这个被初始化的类和它赋值给的那个变量(i.e.左边的变量)有相同的类型。在上面的例子,String就是泛型的类型,应为List变量把String设置为了它的类型。
循环里的泛型
java5有一个新的for循环,叫做for-each, 这东西对于制定泛型的collection处理的很好。来个例子:
List strings = new ArrayList();
//... add String instances to the strings list...
for(String aString : strings){
System.out.println(aString);
}
这个for-each循环迭代在strings列表里的所有String实例。
每次迭代,下一个String实例就赋值给aString变量。这个for-loop循环比原来的while循环更加精小,在while里你不得不迭代地使用collection的迭代器(Iterator)的Iterator.next()方法去获得下个实例,这导致代码臃肿。
泛型之于非collection的其他类型
你当然可以将泛型用于其他class,而非仅仅是collection。你可以将你自己的class泛型化。这个以后再说细节。
2. java中的泛型List(Generic List in Java)
java的List接口(java.util.List)能够被泛型化。这就是说,List的一个实例能够被给定一个类型,所以只有那种类型的实例能插入List中和从List中被读取,这里就是一个例子:
List list = new ArrayList;
这个list现在仅仅和String类型的实例联系,这意味着你只能把String放进这个list。不要放别的进list,编译器会抱怨。
泛型的类型检查,仅仅在编译期检查。在运行时你可以调整代码,使字符串列表具有字符串插入的其他对象。不过这是个坏主意。(At runtime it is possible to tweak your code so that a String List has other objects that String’s inserted. This is a bad idea, though.)
进入一个泛型的列表
如下,你能get和insert泛型list的元素:
List list = new ArrayList;
String string1 = "a string";
list.add(string1);
String string2 = list.get(0);
注意,没必要对List.get()方法中得到的对象进行转型,虽然平常需要。
编译器已经知道这个List只包含String的实例,所以转型(cast)是没有必要的。
在泛型化的列表中的迭代
你可以使用迭代器迭代泛型列表,如下所示:
List list = new ArrayList;
Iterator iterator = list.iterator();
while(iterator.hasNext()){
String aString = iterator.next();
}
跟上面的进入一个泛型的列表里一样,不必转型,在while的跌代器里,你也不必转型。
你也可以使用新的for-loop,如下:
List list = new ArrayList;
for(String aString : list) {
System.out.println(aString);
}
注意,现在有一个String对象,aString,在for-loop的括号里被声明。
每一次的迭代,这个aString都获得了list的当前元素。
3. Java中的泛型集合(Generic Set in Java)
Java的Set接口(java.util.Set)可以被泛型化。也就是说,Set的实例能够被给定一个类型,所以仅有那种类型的实例能在Set中插入,读取。例子如下:
Set set = new HashSet;
这个集合现在仅仅与String类型联系起来了,意味着,只有String类型的实例能够放入这个set里,不要放别的进set,编译器会抱怨。
泛型的类型检查,仅仅在编译期检查。在运行时你可以调整代码,使字符串集合(Set)具有字符串插入的其他对象。不过这是个坏主意。(At runtime it is possible to tweak your code so that a String Set has other objects that String’s inserted. This is a bad idea, though.)
为泛型化的集合添加元素
通常使用add(),一如你平常也常用的
Set set = new HashSet;
String string1 = "a string";
set.add(string1);
那么最大的差别是什么呢?好吧,就是你尝试添加非String的实例进入上述Set,编译器会抱怨。这是个很好的额外的类型检查特性,你值得拥有。
迭代一个泛型化的Set
使用一个iterator(迭代器)吧,如下:
Set set = new HashSet;
Iterator iterator = set.iterator();
while(iterator.hasNext()){
String aString = iterator.next();
}
请注意,就像之前在List那一节所说一样,不必为interator.next()去转型。
因为Set已经被泛型化了(泛型化的意思是有了一个指定的type),编译器知道为你打理一切,不论你使用iterator还是for-loop.
下面就为你展示使用for-loop:
Set set = new HashSet;
for(String aString : set) {
System.out.println(aString);
}
4. java中的泛型Map(Generic Map in Java)
Map这个接口(java.util.Map)也是能够被泛型化的,这就是说,在一个泛型化的Map中,你可以指定为key-value指定特定的类型,这里是例子:
Map set = new HashMap;
这个Map实例set,现在只能接受Integer作为keys,接受String作为values
一样地,泛型的类型检查仅仅发生在编译期。你可以在运行期调整你的代码,这样你的其他实例就能插入了(我翻译时这段话总是不太确定,是能够动态改变key-value对应的原来的Integer-String类型吗?)。尽管这是一个坏主意。
进入(读取)一个泛型化的Map
添加和获得一个泛型化的Map的元素,一如往常,你可以使用put(),get()
Map map = new HashMap;
Integer key1 = new Integer(123);
String value1 = "value 1";
map.put(key1, value1);
String value1_1 = map.get(key1);
所以大的改变在哪呢?(作者应该是在将新的java7特性羞辱旧版java4,我说可能啊)。
在于一个很nice的类型检查:对于上诉例子,当你的key-value对不是Integer-String时,编译器会抱怨。
java5的auto boxing特性能给我们带来很大方便(使得我们的代码叙述更加人性化):
Map map = new HashMap;
Integer key1 = 123;
String value1 = "value 1";
map.put(key1, value1);
//or
map.put(123, value1);
String value1_1 = map.get(123);
迭代一个泛型化的Map
一个Map,有两个collection可以被迭代: key Set 和 value Set。
通常情况下,你迭代key Set,然后通过Map.get(key)来获取value。
来,给你两个例子:
Map map = new HashMap;
//... add key, value pairs to the Map
// iterate keys.
Iterator keyIterator = map.keySet().iterator();
while(keyIterator.hasNext()){
Integer aKey = keyIterator.next();
String aValue = map.get(aKey);
}
Iterator valueIterator = map.values().iterator();
while(valueIterator.hasNext()){
String aString = valueIterator.next();
}
第二个例子
Map map = new HashMap;
//... add key, value pairs to the Map
for(Integer aKey : map.keySet()) {
String aValue = map.get(aKey);
System.out.println("" + aKey + ":" + aValue);
}
for(String aValue : map.values()) {
System.out.println(aValue);
}
同理,不必进行类型检查,编译器知道key的类型一定是Integer,value的值一定是String.
5.java的泛型化类
相关文章暂无相关文章