抽象类与接口
概述:面向对象的设计,复用的重点在于抽象层的复用,而不是某一个具体代码块的复用,这里涉及到两个概念:1.抽象类,2.接口。下面对其进行解析。
抽象类
概念:抽象类是对根源的抽象。在普通类的基础上添加了抽象方法,抽象方法是指没有方法体的方法,抽象方法需要加上abstract关键字,同时类中包含了抽象方法也需要用abstract修饰。
使用原则:
- 抽象方法访问修饰符必须为
public或protected(若为private,则不能被子类继,子类则无法实现该方法),缺省情况下默认为public。 - 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理。
- 抽象类需要用
abstract关键字修饰,类中的抽象方法也需要用abstract修饰。 - 抽象类中定义的抽象方法必须在具体子类中实现,若子类没有实现抽象父类中的所有抽象方法,则子类也为
abstract类型。
易错点:
- 抽象类中可以存在构造方法,其存在目的是属性的初始化,并且子类对象实例化时,依然满足先执行父类构造,再执行子类构造的顺序。
public class abstractClass {
public static void main(String[] args) {
A a = new B();
a.fun1();
}
}
abstract class A{
public A(){
a = 1;
System.out.println("A构造方法");
}
int a;
public abstract void fun1();
}
class B extends A{
public B(){
System.out.println("B构造方法");
}
@Override
public void fun1() {
System.out.println(a);
}
}
打印结果:A构造方法 B构造方法 1
- 抽象类不可以用
final关键字声明。(因为抽象类必须有子类,而final定义的类不允许被继承)。 - 抽象类"可以"使用
static声明。- 外部抽象类不能使用
static声明 - 内部抽象类可以使用
static声明
- 外部抽象类不能使用
public class abstractClass {
public static void main(String[] args) {
A.B b = new C();
b.fun1();
}
}
//编译器报错
static abstract class A{};
abstract class A{
static abstract class B{
public abstract void fun1();
}
}
class C extends A.B{
@Override
public void fun1() {
System.out.println("static静态内部类");
}
}
打印结果:static静态内部类
- 可以直接通过
类名.方法的方式调用抽象类中的static方法。
public class abstractClass {
public static void main(String[] args) {
A.fun1();
B.fun1();
}
}
abstract class A{
public static void fun1(){
System.out.println("static方法");
};
}
class B extends A{
}
打印结果:static方法 static方法
- 抽象类中定义的抽象方法必须在具体子类中实现,因此,不能有抽象构造方法或抽象静态方法。
- 抽象类中的静态成员变量中的访问类型可以任意。
接口
概念:接口是对动作的抽象,使用interface关键字进行声明,接口中所有方法都必须是抽象的。接口中方法定义默认为public abstract类型,接口中的成员变量类型默认为public staitc final。
使用原则:
- 接口只能对方法进行声明,不能有具体的实现。
- 接口可以继承接口,甚至可以继承多个接口。
- 接口需要用
interface关键字修饰。 - 接口中定义的方法必须在具体子类中实现,若实现类没有实现接口中的所有抽象方法,则子类也为
abstract类型。 - jdk1.8中,可以使用default修饰方法,可以避免其他实现类的修改(需要在接口中实现方法体)。
- 在jdk1.8中,新增了static函数,使用static修饰的方法也是抽象方法,拥有自己的方法体,可以使用
接口名.方法名()的形式调用。
public class abstractClass {
public static void main(String[] args) {
new A().fun1();
System.out.println(new A().fun2());
new A().fun3();
i.fun4();
}
}
interface i{
void fun1();
String fun2();
default void fun3(){
System.out.println("fun3");
};
static void fun4(){
System.out.println("fun4");
};
}
class A implements i{
@Override
public void fun1() {
System.out.println("fun1");
}
@Override
public String fun2() {
return "fun2";
}
}
打印结果:fun1 fun2 fun3 fun4
抽象类与接口的异同
相同点:
1.接口和抽象类都不能实例化 2. 都位于继承的顶端,用于被其他实现或继承 3. 都包含抽象方法,其子类必须覆写这些抽象方法
不同点:
| 抽象类 | 接口 | |
|---|---|---|
| 声明关键字 | abstract | interface |
| 构造器 | 可以有构造器 | 不能有构造器 |
| 访问修饰符 | 任意访问修饰符 | 默认为public,不允许定义为private或protected |
| 多继承关系 | 一个类最多只能继承一个抽象类 | 一个类可以实现多个接口 |
| 字段声明 | 抽象类的字段声明可以是任意的 | 字段默认为static和final的 |