目录
1. ADT和OOP中的相等性
1.1 相等关系
相等关系是一种等价关系,即满足自反、对称、传递
可以用"是否为等价关系"来检验equals()是否正确
1.2 Immutable类型的相等
判相等要从A空间来看(用户角度) AF映射到相同结果,则等价
站在外部观察者角度:对两个对象调用任何相同的操作,都会得到相同的结果,则认为这两个对象是等价的。
1.3 == vs. equals()
== 表示的是引用等价性(一般用于基本数据类型的相等判定)
equals()表示的是对象等价性 (用于对象类型相等判定)
在自定义ADT时,需要重写Object 的 equals() 方法
equals()方法的实现
在Objects中实现的缺省equals()是在判断引用相等性(相当于==)
用instanceof操作可以判断对象是否是一种特殊的类型(用instanceof是一种动态类型检查,而不是静态类型检查)
注意:不能在父类中用instanceof判断子类类型
等价的对象必须拥有相同的hashCode;不相等的对象也可以映射为同样的hashCode,但是性能会变差
重写equals方法必须要重写hashCode方法(除非能保证你的ADT不会被放入到Hash类型的集合中)
1.4 mutable类型的相等
观察等价性:在不改变状态的情况下,两个mutable对象是否看起来一致
行为等价性:调用对象的任何方法都展示出一致的结果
对于mutable类型来说,往往倾向于实现严格的观察等价性(但是在有些时候,观察等价性可能导致bug,甚至破坏RI)
注意:如果某个mutable的对象包含在Set集合类中,当其发生改变后,集合类的行为不确定!
1.5 注意事项
Collections 使用的是观察等价性,但是其他的mutable类(如StringBuilder)使用的是行为等价性
对mutable类型,实现行为等价性即可。也就是说只有指向同样内存空间的objects,才是相等的,所以对mutable类型来说,无需重写这两个函数,直接调用Object的两个方法即可。(如果一定要判断两个对象"看起来"是否一致,最好定义一个新方法,e.g. similar() )
immutable类型必须重写equals() 和 hashCode()
mutable类型可以不重写,直接继承自Object
1.6 clone()
clone()创建并返回对象的一个copy
浅拷贝:对于基本数据类型,无影响;对于数组或对象数据类型,浅拷贝只是将内存地址赋值给了新变量,它们指向同一个内存空间。改变其中一个对另一个也会产生影响。
Java中的clone实现的是浅拷贝。
要避免一些问题,建议使用深拷贝。
2. JAVA异常机制
2.1 java异常类别
所有的异常都是从Throwable继承而来的,是所有异常的共同祖先。
Throwable有两个子类,Error和Exception。其中Error是错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。
Exception,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。
2.2 Checked Exception
可检查的异常,这是编码时非常常用的,所有checked exception都是需要在代码中处理的。它们的发生是可以预测的,正常的一种情况,可以合理的处理。比如IOException,或者一些自定义的异常。除了RuntimeException及其子类以外,都是checked exception。
2.3 Unchecked Exception
RuntimeException及其子类都是unchecked exception。比如NPE空指针异常,除数为0的算数异常ArithmeticException等等,这种异常是运行时发生,无法预先捕捉处理的。Error也是unchecked exception,也是无法预先处理的。
2.4 异常的处理
代码中的异常处理其实是对可检查异常的处理。
1.通过try...catch语句块来处理:
try{
// 程序代码
}catch(ExceptionName e1){
//Catch 块
}
Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
2.另外,也可以在具体位置不处理,直接抛出,通过throws/throw到上层再进行处理,具体的,如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。
2.5 finally关键字
finally 关键字用来创建在 try 代码块后面执行的代码块。
无论是否发生异常,finally 代码块中的代码总会被执行。
在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。
finally 代码块出现在 catch 代码块最后。