【Java集合源码】写在前面的适配器模式

最近开始阅读Java集合的源码,但首先被下面这张图困惑了:

【Java集合源码】写在前面的适配器模式_第1张图片可以看到,ArrayList继承了抽象类AbstractList,AbstractList又继承了AbstractCollection类且实现了List接口。

好奇,为什么需要这两个抽象类,不过在此之前需要先弄清两个概念:抽象类、接口

抽象类:

在了解抽象类之前,先来了解一下抽象方法

抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的声明格式为:

abstract void fun(); 

抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象

抽象类的声明格式:

public abstract class ClassName { 
    abstract void fun(); 
} 

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别:

  1. 抽象类不可以直接实例化,只可以用来继承
  2. 子类继承抽象类后,必须实现父类的所有抽象方法, 如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类, 只能用于继承,而不能实例化
  3. 一个类里面定义了抽象方法,那么该类必须定义为抽象类,但是一个抽象类里面可以有抽象方法,也可以没有
  4. 构造方法和静态方法不可以修饰为abstract!!!(注意:static和abstract绝对不是互斥的,虽然两者不能同时修饰某个方法,但他们可以同时修饰内部类)
  5. 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。

 

接口类:

在Java中,定一个接口的形式如下:

public interface InterfaceName { 

    void add (String b);
    /**
     * JDK1.8中接口新特性
     */
    default void delete() {

    }
    static void update(){

    }
} 

接口中可以含有 变量和方法。但!!!接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),方法会被隐式地指定为public abstract方法(JDK1.8之后,接口中的方法不再是只能有抽象方法,他可以有static方法和default方法)

 

抽象类与接口的区别(JDK1.8):

  1. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
  2. 一个类只能继承一个抽象类,而一个类却可以实现多个接口
  3. 抽象类中可以包含非抽象的方法,接口中所有的方法为抽象方法,jdk8之后提供了默认方法和静态方法(且这两种方法可以存在方法体)
  4. JDK 8 争议性的把抽象类的优点带给接口。造成的影响是今天有大量的抽象类通过默认方法可能被替换为接口

 

接下来就要到如此设计的原因的:适配器模式!!

用这些抽象类去实现接口,在抽象类中实现接口中的若干或全部方法,这样下面的一些类只需直接继承该抽象类,并实现自己需要的方法即可,而不用实现接口中的全部抽象方法

为了更好的理解上面的话,仿照这三个类(List、AbstractList、ArrayList)写了如下的demo:

/**
 * List
 */
public interface List {
    void add (String a);

    void remove (String b);

    void size();
}
/**
 * AbstractList
 */
public abstract class AbstractList implements List {

//在抽象类中实现接口中的若干或全部方法,此处我们只实现remove和size

//    @Override
//    public void add(String a) {
//
//    }
    
    @Override
    public void remove(String b) {
        System.out.println("[AbstractList] remove :" + b);
    }

    @Override
    public void size() {
        System.out.println("[AbstractList] size");
    }
}
/**
 * demoList
 */
public class demoList extends AbstractList {

    /**
     * 由于抽象类中没有实现List接口中的add方法,所以在这里要实现父类实现接口的方法
     * @param a
     */
    @Override
    public void add(String a) {

    }

    @Override
    public void remove(String b){
        System.out.println("[demoList] remove : " + b);
    }

}

三个类定义好以后,来写一个测试类测试一下:

public class testDemo {
    public static void main(String args[]){
        demoList demoList = new demoList();
        demoList.remove("aa");    //demoList类重写父类的remove方法
        demoList.size();    //demoList类没有重写父类的size方法
    }
}

测试结果:

可以看到,remove方法执行的是demoList重写的方法,size方法则是AbstractList中实现List接口的方法。

这就是前面所说到的适配器模式抽象类去实现接口,在抽象类中实现接口中的若干或全部方法,这样一些类只需直接继承该抽象类,并实现自己需要的方法即可,而不用实现接口中的全部抽象方法。

 

你可能感兴趣的:(Java源码阅读)