UUID
关于UUID,我们需要知道它最重要的一点,就是它会生成全地球唯一的一个id,它可以作为数据库的主键存在,标识各个元组。 UUID保证对在同一时空中的所有机器都是唯一的,利用机器的当前日期和时间、时钟序列、全局唯一的IEEE机器识别号来生成唯一的一个id。其用法如下:
//得到一个UUID
System.out.println(UUID.randomUUID());
Base64
Base64类是将不是ASCII码的字符串转换为ASCII码格式的,可以做到简单的将密码的明文转变为非明文,但不能做到保密,一般用在网络传输上,需要ASCII码的地方,用法如下:
//编码
String asB64 = Base64.getEncoder().encodeToString("蕾姆".getBytes("utf-8"));
System.out.println(asB64); // 输出为: c29tZSBzdHJpbmc=
// 解码
byte[] asBytes = Base64.getDecoder().decode("6JW+5aeG");
//输出:6JW+5aeG
//蕾姆
Observer
Observer类是Java内置的观察者模式,用一张图来说明下观察者模式:
对观察者模式举个例子的话,就像微信的推送消息,每个微信的使用者都是观察者,公众号就是一个被观察者,当公众号有消息更新后,会同步通知每个观察者说我要进行消息的推送了,然后将消息推送给每个观察者。可以理解为广播模式,被观察者通过广播通知各个观察者。在Java中,定义了一个Observer接口,定义了消息的更新操作:
public interface Observer {
void update(Observable o, Object arg);
}
接着是被观察者:
public class Observable {
//changed表示是否需要更新
private boolean changed = false;
//存贮观察者
private Vector<Observer> obs;
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();
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();
}
}
从源码中看出,该类是个同步类,线程安全,每次更新完都会设置不可更新。如何用这两个类实现一个观察者模式呢?首先,先定义观察者类实现Observer接口,我在这定义了DateUpdateObserver数据更新以及ViewUpdateObserver视图更新:
public class ViewUpdateObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("视图改变了");
}
}
public class DateUpdateObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("数据改变了");
}
}
接着实现被观察者继承Observable 类,因为设置可以更新的方法是保护方法,所以必须继承Observable 类来设置可以更新的值,,我这里为了简便直接在构造器里面设置了:
public class ShowUpdate extends Observable {
public ShowUpdate(){
setChanged();
}
}
测试:
Observable observable=new ShowUpdate();
observable.addObserver(new DateUpdateObserver());
observable.addObserver(new ViewUpdateObserver());
observable.notifyObservers();
//输出:视图改变了 数据改变了
EventListener、RandomAccess
关于这两个接口,阅读过它两源码的同学都知道,它们都是空的接口,没有定义任何东西,是起标记用的:
public interface RandomAccess {
}
public interface EventListener {
}
先说RandomAccess接口,该接口是一个标记为随机访问的接口,是什么意思呢?RandomAccess接口被ArrayList、Vector实现过,是让它判断是否是数组类型的容器的,因为只有数组类型的容器可以用下标来实现随机的访问。这一点用到了Collections容器的选择查找对应值的索引上:
public static <T>
int binarySearch(List<? extends Comparable<? super T>> list, T key) {
if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)
return Collections.indexedBinarySearch(list, key);
else
return Collections.iteratorBinarySearch(list, key);
}
从源码中看出,当容器实现了RandomAccess 接口时,用索引值查找的方式来进行二分搜索,否则就用迭代器来进行,因为数组类型的容器,即ArrayList的索引值查找比迭代器查找快很多。
而EventListener接口可以用来实现自定义的监听器,试想一个网络请求数据的异步场景,当你向服务器请求时,假如这个请求是异步的请求,服务器并不会立马返回,而是需要等待一会儿,这时候你就要写个监听来监听它的数据的返回,我们可以利用这个接口来实现:
public interface NetworkListener extends EventListener {
void success();
void fail();
}
public class NetworkListenerIml implements NetworkListener{
@Override
public void success() {
System.out.println("成功了");
}
@Override
public void fail() {
System.out.println("失败了");
}
}
public class NetworkRequest {
private NetworkListener eventListener;
public void addEventListener(NetworkListener eventListener){
this.eventListener=eventListener;
}
public void request(){
eventListener.success();
}
}
NetworkRequest networkRequest=new NetworkRequest();
networkRequest.addEventListener(new NetworkListenerIml());
networkRequest.request();
这样就把代码间的模块清晰化了,是代码的复用以及可拓展性大大的提高了。