Java编程思想读书笔记(10-11)
第十章 内部类
可以将一个类的定义放在另一个类的定义内部,这就是内部类。
1、创建内部类
创建内部类就是将类的定义置于外围类的里面:
public class Outer {
class Inner {
//...
}
public Inner getInner(){
return new Inner();
}
public static void main(String[] args){
Outer outer = new Outer();
Outter.Inner inner = outer.getInner();
}
}
比较典型的情况是如上面代码所示的情况:外部类将有一个方法,该方法返回一个指向内部类的引用。
如果想从外部类的非静态方法之外的任意位置创建内部类对象,必须使用OuterClassName.InnerClassName的形式具体指明这个对象的类型。
2、链接到外部类
当生成一个内部类对象的时候,此对象与制造他的外部类对象之间就有了一种联系,所以它能访问其外围对象的所有成员,而不需要任何特殊条件。此外,内部类还拥有其外围类的所有元素的访问权。
内部类的对象只能在与其外围类的对象相关联的情况下才能被创建(在内部类是非static类时)。因为构建内部类对象时,需要一个指向其外围类对象的引用,如果编译器访问不到这个引用就会报错。
3、在方法和作用域中的内部类
可以再一个方法里面后者在任意的作用域内定义内部类。这么做有两个理由:
- 你实现了某类型的接口,于是可以创建并返回对其的引用。
- 你要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类时公共可用的。
4、匿名内部类
将方法返回值的生成与这个返回值的类的定义结合在一起。所以这个类时匿名的,他没有名字。
public Test test(){
return new Test{
//...
}
}
- 匿名内部类不能重复使用
- 匿名内部类必须也只能继承一个父类或者实现一个接口
- 匿名内部类不能是抽象的,必须实现父类或者接口的所有抽象方法
- 匿名内部类没有构造方法,不能有静态成员变量和静态方法
- 给匿名内部类传递参数时,若该形参在内部类被使用,那么该形参必须被声明为final
第十一章 持有对象
1、泛型和类型安全的容器
泛型可以使容器存放指定的类型,使类型安全,如果不指定泛型,存放数据时可以存放不同的类型,但是取出来的统一都是Object类型的数据,在使用之前需要知道存放的数据是什么类型,然后进行转型之后才能使用。
2、Java容器
1)Collection
Collection。一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入顺序保存元素,而Set不能有重复的元素。Queue按照排队规则来确定对象产生的顺序(通常与它们被插入的顺序相同)。
2)Map
一组成对的“键值对”对象,允许你使用键来查找值。ArrayList允许你使用数字来查找值,因此在某种意义上讲,他将数字与对象关联在了一起。映射表允许我们使用另一个对象来查找某个对象,它也被称为“关联数组”,因为他将某些对象与另外一些对相关联在了一起;或者被称为“字典”,因为你可以使用键对象来查找值对象,就像在字典中使用单词来定义一样。Map是强大的编程工具。
LinkedList具有再List接口中没有包含的额外方法,TreeMap也具有在Map接口中未包含的方法。如果要使用这些额外方法就不能使用向上转型的方式将他们转为更通用的接口。
Collection初始化可以使用Array.asList()或者Collections.addAll(),后者运行起来要快得多,所以构造一个不包含元素的Collection,然后调用Collection.addAll()方式很方便,因此它是首选方法。
3、容器的打印
数组必须使用Array.toString()来产生可打印表示,但是打印容器无需任何帮助,默认的打印行为即可生成可读性很好的结构。
-
Collection在每个槽中只能保存一个元素,此类容器包括:
1)List,它以特定的顺序保存一组元素;
2)Set,元素不能重复;
3)Queue,只允许在容器的一“端”插入对象,并从另外一“端”移除对象。
-
Map在每个槽内保存两个对象,即键和与之相关联的值。
4、List
有两种类型的List:
-
基本的ArrayList,他长于随机访问元素,但是在List的中间插入和移除元素是较慢
-
LinkedList,他通过代价较低的在List中间进行的插入和删除操作,提供了优化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。
-
常用方法:
【1】subList(fromIndex, toIndex);
从两个参数间截取子list,如果参数相等,则返回list为空。
【2】add(String e)
在list末尾添加元素。
【2.1】add(int index ,String e)
在指定index下插入元素,其他元素后移。
【3】get(int index)
获取指定下标的值,index从 0 开始。
【4】size
获取list的元素个数。
【5】isEmpty()
判断list是否包含元素,此时list一定是实际存在对象!若为null,则抛空指针异常,null对象不能进行isEmpty()判断。
5、迭代器
迭代器是一个对象,它的工作是遍历并选择序列中的对象,二客户端程序员不必知道或关心该序列底层的结构。此外,迭代器通常被称为轻量级对象:创建它的代价小。英雌,经常可以见到对迭代器有些奇怪的限制;例如,Java的Iterator只能单向移动,这个Iterator只能用来:
1)使用方法iterator()要求容器返回一个Iterator。Iterator将准备好返回序列的第一个元素。
2)使用next()获取序列中的下一个元素。
3)使用hasNext()检查序列中是否还有元素。
4)使用remove()将迭代器新近返回的元素删除。
ListIterator是一个更加强大的Iterator的子类型,他只能用于各种List类的访问。尽管Iterator只能向前移动,但是ListIterator可以双向移动。
6、LinkedList
LinkedList与ArrayList相比较,执行插入和移除操作更高效,但是在随机访问操作方面要逊色一些。
LinkedList还添加了可以使其作用栈、队列或双端队列的方法。
7、Stack
“栈”通常是指“后进先出”的容器,有时栈也被成为叠加栈,因为最后“压入”的元素,第一个“弹出”。
8、Set
Set不保存重复的元素;Set最常被使用的是测试归属性,我们可以很容易地询问某个对象是否在某个Set中
存储元素的方式:
- HashSet:使用散列函数
- LinkedHashSet:使用散列,但是看起来使用了链表来维护元素的插入顺序
- TreeSet:将元素存储在红-黑树结构中
9、Map
Map是存入一对键值对的容器,通过key来取得value。
Map常见方法
get(Object o):返回指定键所映射的值,如果不包含该键的映射关系,返回null
put(K key, V value):将指定的值与此映射中的指定键关联,如果已经存在映射关系,更新值
hashCode():返回此映射的哈希码值
Map的三种实现
HashMap:基于“拉链法”实现的散列表,一般用于单线程中,不是线程安全的
HashTable:基于“拉链法”实现的散列表,一般用于多线程中,是线程安全的
TreeMap:有序的散列表,通过红黑树实现的,一般用于单线程中存储有序的映射
hashCode():返回此映射的哈希码值
Map的三种实现
HashMap:基于“拉链法”实现的散列表,一般用于单线程中,不是线程安全的
HashTable:基于“拉链法”实现的散列表,一般用于多线程中,是线程安全的
TreeMap:有序的散列表,通过红黑树实现的,一般用于单线程中存储有序的映射