文章标题
来源:互联网 发布:怎么修改tomcat的端口 编辑:程序博客网 时间:2024/05/21 11:35
Java编程思想 第11章 持有对象
标签(空格分隔): JAVA学习
11.1 泛型和类型安全的容器
class Apple { private static long counter; private final long id = counter++; public long id() { return id; }}class Orange {}public class ApplesAndOrangesWithoutGenerics { @SuppressWarnings("unchecked") public static void main(String[] args) { ArrayList apples = new ArrayList(); for (int i = 0; i < 3; i++) { apples.add(new Apple()); } // Not prevented from adding an Orange to apples: apples.add(new Orange()); for (int i = 0; i < apples.size(); i++) { ((Apple)apples.get(i)).id(); // Orange is detected only at run time } }}
Apple和Orange类是有区别的,它们除了都是Object之外没有任何共性(如果一个类没有显式地声明继承自哪个类,那么它自动地继承自Object)。因为ArrayList保存的是Object,因此apples容器不仅可以添加Apple对象,还可以添加Orange对象,而且无论在编译期还是运行时都不会有问题。
但是在运行时,当试图将Orange对象转型为Apple时,就会得到异常:
Exception in thread "main" java.lang.ClassCastException: com.java.chapter11.Orange cannot be cast to com.java.chapter11.Apple at com.java.chapter11.ApplesAndOrangesWithoutGenerics.main(ApplesAndOrangesWithoutGenerics.java:26)
使用泛型,就可以在编译期防止将错误类型的对象放置到容器中。
public class ApplesAndOrangesWithoutGenerics2 { public static void main(String[] args) { ArrayList<Apple> apples = new ArrayList<Apple>(); for (int i = 0; i < 3; i++) { apples.add(new Apple()); } // Compile-time error:// apples.add(new Orange()); for (int i = 0; i < apples.size(); i++) { System.out.println(apples.get(i).id()); } for (Apple c : apples) { System.out.println(c.id()); } }}/* Output:012012*/
现在,编译器可以阻止你将Orange放置到apples中,因此它变成了一个编译期错误,而不再是运行时错误。
向上转型也可以像作用于其他类型一样作用于泛型:
class GrannySmith extends Apple {}class Gala extends Apple {}class Fuji extends Apple {}class Braeburn extends Apple {}public class GenericsAndUpcasting { public static void main(String[] args) { ArrayList<Apple> apples = new ArrayList<Apple>(); apples.add(new GrannySmith()); apples.add(new Gala()); apples.add(new Fuji()); apples.add(new Braeburn()); for (Apple c : apples) { System.out.println(c); } }}/* Output:com.java.chapter11.GrannySmith@325dfb22com.java.chapter11.Gala@147e8bd9com.java.chapter11.Fuji@f5e12com.java.chapter11.Braeburn@70e8efc5*/
11.2 基本概念
Java容器类类库的用途是“保存对象”,并将其划分为两个不同的概念:
* Collection : 一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照排队规则来确定对象产生的顺序。
* Map : 一组成对的“键值对”对象,允许你使用键来查找值。
11.3 添加一组元素
public class AddingGroups { public static void main(String[] args) { Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 34, 5)); Integer[] moreInts = {6, 7, 8, 9, 10}; collection.addAll(Arrays.asList(moreInts)); // Runs significantly faster, but you can't // construct a Collection this way: Collections.addAll(collection, 11, 12, 13, 14, 15); Collections.addAll(collection, moreInts); // Produces a list "backed by" an array: List<Integer> list = Arrays.asList(16, 17, 18, 19, 20); list.set(1, 99); // OK -- modify an element// list.add(21); // Runtime error because the underlying array cannot be resized }}
Arrays.asList()方法的限制是它对所产生的List的类型做出了最理想的假设,而并没有注意你对它会赋予什么样的类型。有时这就会引发问题:
class Snow {}class Powder extends Snow {}class Light extends Powder {}class Heavy extends Powder {}class Crusty extends Snow {}class Slush extends Snow {}public class AsListInference { public static void main(String[] args) { List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(), new Powder()); // Won't compile: // Compiler says: // found : java.util.List<Powder> // required : java.util.List<Snow>// List<Snow> snow2 = Arrays.asList(new Light(), new Heavy()); List<Snow> snow3 = new ArrayList<Snow>(); Collections.addAll(snow3, new Light(), new Heavy()); // Give a hint using an // explit type argument specification: List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Powder()); }}
11.4 容器的打印
public class PrintingContainers { static Collection fill(Collection<String> collection) { collection.add("rat"); collection.add("cat"); collection.add("dog"); collection.add("dog"); return collection; } static Map fill(Map<String, String> map) { map.put("rat", "Fuzzy"); map.put("cat", "Rags"); map.put("dog", "Bosco"); map.put("dog", "Spot"); return map; } public static void main(String[] args) { System.out.println(fill(new ArrayList<String>())); System.out.println(fill(new LinkedList<String>())); System.out.println(fill(new HashSet<String>())); System.out.println(fill(new TreeSet<String>())); System.out.println(fill(new LinkedHashSet<String>())); System.out.println(fill(new HashMap<String, String>())); System.out.println(fill(new TreeMap<String, String>())); System.out.println(fill(new LinkedHashMap<String, String>())); }}/* Output:[rat, cat, dog, dog][rat, cat, dog, dog][cat, dog, rat][cat, dog, rat][rat, cat, dog]{cat=Rags, dog=Spot, rat=Fuzzy}{cat=Rags, dog=Spot, rat=Fuzzy}{rat=Fuzzy, cat=Rags, dog=Spot}*/
ArrayList和LinkedList都是List类型,它们都按照被插入的顺序保存元素。两者的不同之处仅仅在于执行某些类型的操作时的性能,而且LinkedList包含的操作也多于ArrayList。
HashSet、TreeSet和LinkedHashSet都是Set类型,输出显示在Set中。每个相同的项只保存一次,但是存储元素的方式不同。
- HashSet:存储的顺序没有意义,是最快的获取元素方式。
- TreeSet:按照比较结果的升序保存对象。
- LinkedHashSet:按照被添加的顺序保存对象。
11.5 List
List接口在Collection的基础上添加了大量的方法,使得可以在List的中间插入和移除元素。
有两种类型的List:
- 基本的ArrayList,它长于随机访问元素,但是在List的中间插入和移除元素时较慢。
- LinkedList,它随机访问方面相对比较慢,但通过较低的代价在List中间进行插入和删除操作,提供了优化的顺序访问。
11.6 迭代器
List<Pet> pets = Pets.arrayList(12);Iterator<Pet> it = pets.iterator();while (it.hasNext()) { Pet p = it.next();}
11.6.1 ListIterator
- Iterator的子类型
- 只能用于各种List类的访问
- Iterator只能向前移动,ListIterator可以双向移动
11.7 LinkedList
11.8 Stack
11.9 Set
11.10 Map
11.11 Queue
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- IOS 星星评分控件-Swift3.0
- Linux下hydra的使用
- Ubuntu 安装和修改Apache2端口
- 查找(一)
- 文章标题
- 文章标题
- python中的文件数据保存
- 文章标题
- SSD6 Exercise0: 函数指针数组的使用实例
- python中的文件读取注意事项
- SpringMVC之类型转换Converter
- 理解差分约束(转)
- HDU 3699(J) ——A hard Aoshu Problem(DFS暴力搜索)
- python爬虫学习第一天