1.抽象类
1.1抽象类的概念
抽象类是面向对象编程中的一个重要概念,它主要用于定义一个或多个抽象方法的类。抽象类中又抽象方法,而且抽象类时无法被实例化的,毕竟叫做抽象类。其用途就是继承。
1.2抽象类语法
在Java中,使用 abstract
关键字来声明一个类为抽象类,使用 abstract
关键字来声明抽象方法,由于是抽象方法,因此抽象类方法的方法体并没有内容。
abstract class Animal {
// 抽象方法
abstract void eat();
// 非抽象方法
void sleep() {
System.out.println("Animal is sleeping.");
}
}
class Dog extends Animal {
@Override
void eat() {
System.out.println("Dog is eating.");
}
}
1.3抽象类的特点
注意:抽象类也是类,也可以拥有普通方法和属性,甚至构造方法。
1.不能被实例化:抽象类不能被直接实例化,因为它代表了一种抽象的概念或行为,没有具体的实现。
以上面的Animal抽象类为例,下面的代码就是错误的。
Animal animal = new Animal();
2.可以包含抽象方法:抽象类可以包含抽象方法,这些方法是只有声明而没有实现(即没有方法体)的方法。抽象方法必须以abstract
关键字声明。
abstract class Animal {
// 抽象方法
abstract void eat();
// 非抽象方法
void sleep() {
System.out.println("Animal is sleeping.");
}
}
3.可以包含非抽象方法:抽象类不仅可以包含抽象方法,还可以包含已经实现了的方法(即非抽象方法)。这些方法可以直接在抽象类中提供具体的实现,供子类继承和使用。
abstract class Animal {
// 抽象方法
abstract void eat();
// 非抽象方法
void sleep() {
System.out.println("Animal is sleeping.");
}
}
注意:抽象类可以不包含抽象方法,但如果方法是抽象的,那么类也必须是抽象类。
4.子类必须实现抽象方法(如果子类不是抽象的):如果子类继承了一个抽象类,并且这个抽象类中包含抽象方法,那么子类必须实现这些抽象方法,也就是重写,除非子类也被声明为抽象类。这意味着,子类必须提供抽象方法的具体实现,才能被实例化。
5.抽象类不能被fianl和static修饰:因为子项需要进行重写。
5.可以包含静态方法和静态字段:和普通类一样,抽象类也可以包含静态方法和静态字段。
6.构造函数:抽象类可以有构造函数,尽管它不能被直接实例化。构造函数在创建子类对象时被调用,用于初始化父类部分的状态。
2.接口
2.1接口的定义
在Java中,接口(Interface)是一种引用类型,是一种抽象的类型,用于指定一组方法规范,但不提供这些方法的具体实现。接口是一种完全抽象的类,它不能被实例化。接口中所有的方法都是抽象方法(Java 8之前)。
2.2接口的语法
接口使用interface
关键字来声明
public interface Animal {
// 抽象方法,没有方法体
void eat();
}
一个类通过implements
关键字来实现一个或多个接口。
public class Dog implements Animal {
// 必须实现接口中的所有抽象方法
@Override
public void eat() {
System.out.println("Dog is eating.");
}
public void brak(){
System.out.println("Dog is braking.");
}
}
2.3接口的特性
1.接口是抽象的,无法实例化。
2.接口中的所有方法默认都是public abstract
的,也只能是public abstract
3.接口中不能包含实例变量(即不能定义非静态变量),但可以定义常量(即public static final
变量)。
public interface Animal {
// 抽象方法,没有方法体
void eat();
double age = 3.0; // 默认被:final public static修饰
}
4.接口可以被另一个接口继承,使用extends
关键字。当一个接口继承另一个接口时,它会自动获得被继承接口中声明的所有方法,可以进行多继承。
5.一个类可以实现多个接口,从而具有多个类型。
// 定义一个接口Flyable
interface Flyable {
void fly();
}
// 定义一个接口Swimmable
interface Swimmable {
void swim();
}
// 定义一个类Duck,它实现了Flyable和Swimmable接口
class Duck implements Flyable, Swimmable {
// 实现Flyable接口的fly方法
@Override
public void fly() {
System.out.println("Duck is flying");
}
// 实现Swimmable接口的swim方法
@Override
public void swim() {
System.out.println("Duck is swimming");
}
// Duck类还可以有自己的方法和属性
public void quack() {
System.out.println("Duck is quacking");
}
}
// 测试类
public class TestMultipleInterfaces {
public static void main(String[] args) {
Duck duck = new Duck();
// 作为Flyable类型的Duck
Flyable flyableDuck = duck;
flyableDuck.fly(); // 输出: Duck is flying
// 作为Swimmable类型的Duck
Swimmable swimmableDuck = duck;
swimmableDuck.swim(); // 输出: Duck is swimming
// 作为Duck自身的类型
duck.quack(); // 输出: Duck is quacking
}
}
在这个例子中,Duck
类实现了Flyable
和Swimmable
两个接口,因此它必须提供这两个接口中所有方法的具体实现。 Duck
类不仅可以被视为是Flyable
类型、Swimmable
类型还有被视为它自身的Duck
类型。
6.接口中不能有静态代码块和构造方法。
3.接口与抽象类的区别
接口是形容词,抽象类是名词,
抽象类是将具有共同特征的对象进行抽象,就像汽车的抽象类,就会描述所有汽车的共同特性,比如尺寸大小,外观颜色,等等之类的,但这些描述的字段或方法不带实现,由继承抽象类的类进行实现。
接口是对某种能力的抽象,一个接口通常只包含一组行为,后面的类继承这个接口,就代表这个类可以有执行这个行为的能力。 因此在接口的命名上,往往会加上able。
除了这些概念的差异,其使用方法上也有不同。
接口(Interface) | 抽象类(Abstract Class) | |
成员定义 | 只能包含抽象方法(Java 8+允许默认方法和静态方法)。 | 可以包含抽象方法、普通方法、属性(变量,包括静态和非静态)、构造器和初始化块。 |
成员变量 | 默认为public static final ,即常量。 | 可以是public 、protected 、private 等修饰的静态或非静态变量。 |
方法 | 抽象方法(无实现体),Java 8+可包含默认方法和静态方法。 | 抽象方法和普通方法(有实现体)。 |
构造方法 | 不能包含构造方法。 | 可以包含构造方法,但通常用于被子类调用进行初始化。 |
初始化块 | 不能包含初始化块。 | 可以包含静态和非静态初始化块。 |
继承与实现 | 一个类可以实现多个接口。 | 一个类只能继承一个直接父类(可以是抽象类)。 |
接口之间 | 支持多继承,一个接口可以继承自多个其他接口。 | 不适用(因为类是单继承的)。 |