1.里氏替换原则
里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。
类型替换:
①子类型只能增加而不能删除方法
②子类型需要实现抽象类中所有未实现的方法
③子类型中重写的方法,它的返回值必须是相等类型或是协变类型。
④子类型中重写的方法,它的返回值必须是相等类型或是逆变类型(java不支持)。
⑤子类型中重写的方法不能抛出额外的异常(必须是被重写方法抛出的异常及其子类)。
方法重写:
①更强的不变量(规则限制)
②更弱的前置条件
③更强的后置条件
2.协变、逆变
协变:子类型代替父类型出现,更具体
比如数组中相应子类型的数组引用可以传给父类型
比如泛型中的通配符<?> <? extends xxx>
逆变:父类型代替子类型出现,更抽象
3.委托
一个对象请求另一个对象的功能
与继承相比,主要发生在对象层面,可以选择性的使用方法,比继承更自由。
①将其传入一个具体方法的参数,用完就解除关系。
②将其写入构造函数的参数中,并设立一个字段与委托对象建立联系。
③直接将其固定在一个字段中。
④将其写入一个字段中,并可通过set()方法更改。
4.黑盒框架、白盒框架
白盒框架:通过继承框架类,重写框架方法使用框架
允许扩展每一个非私有方法
需要理解父类的实现
一次只进行一次扩展
通常被认为是开发者框架
黑盒框架:通过委派、组合、调用方法,使用框架类,内部不可见。
允许在接口中对public方法扩展
只需要理解接口
通常提供更多的模块
通常被认为是终端用户框架,平台
5.常用接口、功能类总结
Iterator、Iterable
iterator是一个接口
package java.util;
public interface Iterator<AnyType>
{
boolean hasNext();
AnyType next();
void remove(); //上次next执行结果的元素
}
iterable是一个泛型接口
package java.lang;
public interface Iterable<AnyType>
{
Iterator<AnyType> iterator();
}
删除元素的三种方式
1.普通for循环
2.迭代器删除
Iterator<String> it = list.iterator();
while(it.hasNext()) {
if("b".equals(it.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
it.remove();
}
}
for(Iterator<String> it2 = list.iterator(); it2.hasNext();) {
if("b".equals(it2.next())) {
//list.remove("b"); //不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
it2.remove();
}
}
3.另一种for循环
for (String string : list) {
if("b".equals(string)){
list.remove("b");
}
}
Observer、Observable
Observer:接口、观察者
package java.util;
public interface Observer {
void update(Observable o, Object arg);
}
Observable:类、被观察者
package java.util;
public class Observable {
private boolean changed = false; //是否改变状态
private Vector obs; //Vector利用同步方法来线程安全,线程安全在多线程情况下不会造成数据混乱
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed) //状态值未改变时返回,不通知
return;
arrLocal = obs.toArray(); //将Vector转换成数组
clearChanged(); //重置状态
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
Comparable、Comparator
Comparable是排序接口。若一个类实现了Comparable接口,就意味着该类支持排序。实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
此外,实现此接口的对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器。该接口定义如下:
package java.lang;
import java.util.*;
public interface Comparable<T>
{
public int compareTo(T o);
}
Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过实现Comparator来新建一个比较器,然后通过这个比较器对类进行排序。该接口定义如下:
package java.util;
public interface Comparator<T>
{
int compare(T o1, T o2);
boolean equals(Object obj);
}
注意:1、若一个类要实现Comparator接口:它一定要实现compare(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
2、int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
排序
数组排序:Array.sort(int[] a)
List item
集合排序:
1.Collections.sort(List list)
2.Collections.sort(List list,Comparator c)