一、变量
1. 接口只能是static final 修饰的静态常量。
public interface Animals {
public static final int i=0;
}
2. 抽象类可以有任何权限修饰符修饰的成员变量,也可以有静态成员变量或者静态常量。
public abstract class AbstractFish implements Animals{
//静态变量
static String name= "小张";
//普通成员变量
int age= 18 ;
//静态常量
public static final String sex = "男";
//私有成员变量
private String address = "二仙桥";
//受保护的成员变量
protected String nickName= "义薄云天张大仙";
}
———————————————————————————————————————————
二、构造方法
1.接口没有构造方法
2.抽象类可以有构造方法。
public abstract class AbstractFish implements Animals{
String name;
//无参构造
public AbstractFish(){}
//有参构造
public AbstractFish(String name){
this.name=name;
}
}
这里其实有一个可以注意的点,那就是抽象类不能被实例化,那么给抽象类写构造方法有什么用?
首先构造器并不是用来实例化对象的,是用来为类中的变量赋值,进行初始化。类的实例化是在初始化完成之后。
子类继承父类,当实例化子类时,会隐形先调用父类的构造方法,正如上文所讲,调用构造方法并不代表着父类也会实例化。
所以,尽管抽象类不能被实例化,抽象类并不能调用自己的构造方法,但是我们可以通过构造函数链,在子类中通过super调用抽象类的构造方法,为抽象类的变量进行赋值初始化。
class GrassFish extends AbstractFish{
public GrassFish(){
//一般都会隐性调用super(),在这里我们可以显性调用抽象类的构造方法,为成员变量赋值
super("花果山水帘洞美猴王齐天大圣孙悟空");
}
@Override
public void isRiverFish() {
}
@Override
public void swim() {
}
@Override
public void run() {
}
}
———————————————————————————————————————————
三、普通方法
1. 接口中只能有抽象方法。
public interface Animals {
public abstract void eat();
public abstract void swim();
public abstract void run();
}
2. 抽象类中可以有自己定义的实现了的普通方法,也可以有没实现的抽象方法或者静态方法。
public abstract class AbstractFish implements Animals{
//抽象类自己定义的未实现的抽象方法
public abstract void isRiverFish();
//抽象类自己定义的实现了的普通静态方法
private static void isFood(){
System.out.println("我是可以吃的那类鱼!");
}
//实现了Animals接口部分方法,并没有实现所有方法,抽象类可以只实现接口的部分方法
@Override
public void eat() {
System.out.println("哈哈哈");
}
}
注意:
之前看集合容器的源代码时,我发现了Collection接口下,有一个实现了Collection接口的AbstractCollection抽象类,该类只实现了Collection接口的部分方法。然后底层又有一个AbstractList抽象类继承了AbstractCollection类,最终ArrayList继承了AbstractList抽象类。
但是同时,又有一个List接口继承了Collection接口,AbstractList抽象类不仅继承了AbstractCollection抽象类,同时也实现了List接口,然后ArrayList也是如此。
我的疑问就是为什么不直接用Collection接口下来的List接口就完了,还要弄一个抽象类旁支出来给实现类继承。
解释是,AbstractCollection抽象类实现Collection接口部分方法,这一部分方法是所有Collection接口下具体实现类都可以通用的方法,如果不这样做,那么就会频繁重写方法,效率低。然后AbstractList抽象类又继承AbstractCollection,进一步实现List下可以通用的方法。
至于最终AbstractList已经实现了List接口,ArrayList为什么还要再一次实现List接口,这和序列化相关,如果这里不实现的话,序列化不会通过。
———————————————————————————————————————————
关于访问权限
抽象类理论上来说可以使用任何访问权限符,但是使用private的话没有意义,因为抽象类本来就是要拿给子类进行继承,设置私有化,那子类也访问不了,没有任何的意义。
补充 JDK8之后,允许接口使用default和static关键字。JDK9接口允许使用private static方法。