Java编程思想 第11章 持有对象
2017-07-25 23:11
441 查看
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: 0 1 2 0 1 2 */
现在,编译器可以阻止你将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@325dfb22 com.java.chapter11.Gala@147e8bd9 com.java.chapter11.Fuji@f5e12 com.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
相关文章推荐
- 《Java 编程思想》第11章 持有对象 笔记
- java编程思想学习_第11章_持有对象
- JAVA 编程思想第11章--持有对象
- [学习笔记][Java编程思想]第11章:持有对象
- Java编程思想:第11章 持有对象
- [Java编程思想]第11章 持有对象
- Java编程思想-11持有对象
- 11持有对象-Java编程思想
- java编程思想笔记--持有对象部分一
- java编程思想-11持有对象
- java 编程思想 11章 持有对象 练习15
- 《Java 编程思想》--第十一章:内持有对象
- JAVA编程思想学习笔记十一:持有对象
- JAVA编程思想学习总结:第十一章持有对象
- java编程思想笔记--持有对象部分三
- Java编程思想——持有对象
- JAVA编程思想-第十一章 持有对象
- 11持有对象-Java编程思想
- java编程思想-持有对象
- Java编程思想笔记第十一章(持有对象)