持有对象
——总结《java 编程思想》
collection的构造器可以接受另一个collection用它来将自身初始化,因此可以使用Array.List()为这个构造器产生输入。但是collection.addAll()方法运行起来要快的多。因此构建一个不包含元素的collection,然后调用collection.addAll()这种方法很方便。
List
将元素维护在特定的序列中。有两种List
- 基本的ArrayList,用于随机访问元素,但是在list的中间插入和删除元素时比较慢
- linkedList,通过代价较低的list中间进行插入和删除操作,提供了优化的顺序访问。linkedList在随机访问方面比较慢,但是它的特性集较ArrayList更大。
迭代器:迭代器是一个对象,用于遍历并选择序列中的对象,客户端程序员不必知道或关心该序列的底层结构。有被称为轻量级对象。
java的iterator只能单向移动。listIterator是iterator的子类型,只能用于各种list的访问,可以双向移动。
在linkedList中。getFirst()和element()都返回列表的头并不移除它,如果list为空则抛出NosuchElementException错误,peek()作用一样,不过在列表为空的时候返回null。removeFirst()和remove()、poll()差别类似。
Stack
通常指后进先出的容器。又被称为叠加栈。
linkedList具有能够实现栈的所有功能的方法。
任何对stack的引用都将使用net.mindview.util版本,在选择java.util.stack时,必须使用全限定名称。
Set
Set具有与collection完全一样的接口,因此没有任何额外的功能。实际上set就是collection,只是行为不同(继承与多态的典型思想)。set是基于对象的值来确定归属性的。
Map
将对象映射到其它对象的能力是一种解决编程问题的杀手锏。
Queue
典型的先进先出的容器,在并发编程中十分重要。
linkedList提供方法以支持队列的行为,并且实现了queue接口,因此linkedList可以看做是queue的一种实现。通过将linkedList向上转型为queue。
PriorityQueue:优先级队列
collection与iterator
collection是描述所有序列容器的根接口。java.util.AbstractCollection类提供了 collection默认实现,使得可以创建自己的AbstractCollection的子类型。java中使用迭代器而不是collection表示容器之间的共性。因此实现collection就意味着要提供iterator()方法。
异常
java的基本理念是:结构不佳的代码不能运行
异常情形和普通异常:
异常情形指阻止当前方法或作用域继续执行的问题。所谓的普通问题是指在当前环境下能得到足够的信息,总能处理这个错误。而对于异常情形,就不能继续下去了,因为在当前环境下无法获得必要的信息来解决问题,所能做的就是从当前环境跳出,并且把问题提交给上一级环境。这就是抛出异常发生的事情。
当抛出异常后。首先将使用new在堆上创建异常对象。然后,当前的执行路径被终止,并且从当前环境中弹出对异常对象的引用。此时,异常处理机制接管程序,并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序,它的任务是将程序从错误状态中回复,以使程序能要么换一种方式运行,要么继续运行下去。
所有标准异常类都有两个构造器:一个是默认构造器,一个是接受字符串作为参数,以便能把相关信息放入异常对象的构造器。
异常的终止与恢复:异常处理理论上有两种基本模型,终止模型和恢复模型。
- 假设错误非常关键,一旦异常被抛出就表明错误已无法挽回,也不能回来继续执行。
- 异常处理程序的工作是修正错误,然后重新尝试调出问题的方法,并认为第二次能够成功。
异常说明:使用附加的throws,后面接所有潜在异常类型的列表。用以告知某个方法可能会抛出的异常类型,属于方法声明的一部分。
异常链:一种面向对象的编程技术,将捕获到的异常重新封装到一个新的异常中,并重新抛出。Throwable类及其所有的子类都提供了带cause参数(这个cause就异常原由,代表着原始异常,即使在当前位置创建并抛出行的异常,也可以通过这个cause追踪到异常最初发生的位置)的构造器,其他的异常类就只有通过initCause()来设置cause了。
class MyException1 extends Exception{
}
class MyException2 extends Exception{
MyException2(Throwable throwable){
super(throwable);
}
MyException2(){
super();
}
}
public class ClassInterface {
public void f() throws MyException2{
try {
g();
} catch (MyException1 e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new MyException2();
// 修改后的代码
// throw new MyException2(e);
// 调用MyException2的有参构造函数(并调用父类有参构造),把MyException1当作cause传递进去,这样的话就能获取到MyException1的信息了
}
}
public void g() throws MyException1 {
throw new MyException1();
}
public static void main(String[] args) {
try {
new ClassInterface().f();
} catch (MyException2 myException2) {
myException2.printStackTrace();
}
}
}
printStackTrace() 方法所提供的的信息可以通过getStackTrace()方法来直接访问。这个方法将返回一个由栈轨迹中的元素所构成的数组,其中每一个元素都表示栈中的一帧。如果只是把当前异常对象重新抛出,那么printStackTrace()方法显示的将是原来异常抛出点的调用栈信息,而并非重新抛出点的信息。要想更新这个信息,可以调用fillInStackTrace()方法,这将返回一个Throwable对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的。
异常性能差是因为fillInStackTrace方法,该方法是带锁的并且需要填充线程异常栈信息。
而我们的业务类异常是不需要记录异常栈的,可以考虑覆写fillInStackTrace方法减小性能开支。
只能代码中忽略runtimeException(以及子类)类型的异常,其它类型异常的处理都是编译器强制实施的。因为runtimeException是编译错误
当涉及到break和continue语句的时候,finally子句也会得到执行。如果把finally子句和带标签的break和continue配合使用,在java中就没必要使用goto语句了。