ArrayList类继承关系如下图所示:

java 实例化arraylist时给一个默认值 java arraylist int_java

ArrayList是对接口List的一个实现,其能够自动扩展容量,同时其可以存放null值(即 ArrayList.add(null)),它与Vector类很相似,但是ArrayList里的方法不是 synchronized,即其非线程安全(注意 虽然说Vector里的方法是synchronized,但也不能保证其一定是线程安全的,可见Vector是否线程安全)。ArrayList实际上是通过一个 Object[] 数组来保存实际的元素,同时通过成员变量size记录Object[]数组里实际存储了多少个元素。

ArrayList实现的三个接口 SerializableCloneableRandomAccess相当于声明一样,什么都没做。

图中多了两个抽象类 AbstractListAbstractCollect,先梳理下抽象类实现接口

抽象类实现接口


  • java中接口里的方法默认为 public abstract,一个实体类如果实现某个接口,那么其必须实现这个接口中的所有方法
public interface interface1 {
    public void add(int a,int b);
    public int sub(int a,int b);
}
/*实体类必须实现接口中的所有方法*/
public class EntityClass implements interface1{
    @Override
    public void add(int a, int b) {
        // TODO Auto-generated method stub      
    }
    @Override
    public int sub(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }
}
  • 抽象类可以包含抽象方法,也可以不包含任何抽象方法;当一个类继承抽象类时,如果这个抽象类包含了抽象方法,那么这个子类要么实现父抽象类的所有抽象方法,要么把自己也声明为抽象类,则其可以不实现父抽象类的任何抽象方法,也可以实现一个或多个抽象方法;
public abstract class AbstractClass{
    public abstract int div(int a,int b);
    public abstract int div2(int a,int b);
    public int div3(int a,int b){
        return a/b;
    }
}
/*实体类需要实现父抽象类的所有抽象方法*/
public class EntityClass extends AbstractClass{
    @Override
    public int div(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }
    @Override
    public int div2(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }
}

或者

/*把自己也声明为抽象类,则其可以不实现父抽象类的任何抽象方法,也可以实现一个或多个抽象方法*/
public abstract class EntityClass extends AbstractClass{
    @Override
    public int div(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }
}

如果被继承的抽象类不包含任何抽象方法,那么子类是不是抽象类也就没什么关系了,不过一般也不会有一个独立的抽象类不包含任何抽象方法。

那么如果用抽象类实现接口,然后实体类再去继承抽象类会怎样呢?这也是图中ArrayList的实现方式。
前面说过,接口里所有的方法默认为abstract类型的,其实我们可以把接口看成是一个只能包含抽象方法的抽象类

于是:

  • 当一个抽象类实现接口的时候,其可以不实现接口的任何方法,此时接口的方法就相当于这个抽象类的抽象方法,当一个实体类继承这个抽象类时,其必须实现抽象类的所有抽象方法(当然也就包括了接口里的所有方法)
public interface interface1 {
    public void add(int a,int b);
    public int sub(int a,int b);
}
/*可以不实现接口中的任何方法*/
public abstract class AbstractClass implements interface1{

}
/*必须实现抽象类的所有抽象方法(实际上这两个方法是父抽象类实现的接口中的)*/
public class EntityClass extends AbstractClass{
    @Override
    public void add(int a, int b) {
        // TODO Auto-generated method stub

    }
    @Override
    public int sub(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }

}
  • 当抽象类实现了接口中的某些方法时,这些方法便成为了这个抽象类的非抽象方法,当实体类继承这个抽象类的时候,其便不需要实现在抽象类中已经实现了的接口的方法
public interface interface1 {
    public void add(int a,int b);
    public int sub(int a,int b);
}
/*实现接口中的add方法,不实现sub方法,此时add变为了非抽象方法*/
public abstract class AbstractClass implements interface1{
    @Override
    public void add(int a, int b) {
    }
}
/*必须实现未在父抽象类中实现的sub方法,而不需实现add方法*/
public class EntityClass extends AbstractClass{
    @Override
    public int sub(int a, int b) {
        // TODO Auto-generated method stub
        return 0;
    }   
}

那么在实体类与接口之间加上一个抽象类有什么好处呢?可参见:Java抽象类实现接口


我们回到ArrayList中,可以看到ArrayList在继承了AbstractList(AbstractList实现了List接口)的同时还直接实现List,这是为什么?按道理可以不用直接实现List啊,因为其继承的AbstractList已经实现了List。