什么是标记接口?
最早还是在看源码的时候有印象,例如下面是ArrayList的源码:
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
实现了RandomAccess接口、Cloneable接口和Serializable接口。然而我们可以发现,这三个接口里面啥都没写,例:
public interface RandomAccess {
}
一般认为这种,没有任何方法的接口是标记接口。并不是Java的语法,而是一种设计理念。
一个关于RandomAccess的简单的例子
RandomAccess,随机访问。简单说,就是声明了该类是否可以被随机访问。例如数组,可以通过下标访问一个具体的元素,那么这个就是可以随机访问。ArrayList的底层是数组,自然可以随机访问喽,而LinkedList底层是双向链表,自然是不能了。那么,我们在设计的时候,有这样的思想:get()方法是获取某个元素的,而List不管有多少的实现类——一定是有的将数组当底层,有的是链表,也有的用其他的数据结构。但是总而言之——能够被随机访问的数组,我们可以通过下标直接获取元素,而其他的只能通过遍历来获取。
我们化简一下,假设只有ArrayList和LinkedList,然后在写AbstractList中get方法,可以这样:
package me.iwts;
interface RandomAccess {
}
class AbstractList {
public void get(int index) {
if(this instanceof RandomAccess) {
System.out.println("random");
}else{
System.out.println("no");
}
}
}
class ArrayList extends AbstractList implements RandomAccess {
}
class LinkedList extends AbstractList {
}
public class Main {
public static void main(String[] args){
ArrayList list = new ArrayList();
LinkedList list1 = new LinkedList();
list.get(1);
list1.get(1);
}
}
可能看完上面的代码,已经能够理解什么是标记接口了。
利用多态,将get()方法的实现在父类中写,子类只用使用就行了。而RandomAccess仅仅是一个标记——标记该类是用数组的,可以被随机访问。自然,实现这样的写法,用继承太蛋疼了,用接口就非常方便。