
🎁个人主页:User_芊芊君子
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:【Java】内容概括
【前言】
在Java面向对象编程中,抽象类
和接口
是两个非常重要的概念,它们为代码的抽象化、模块化和可扩展性提供了强大的支持。无论是开发大型企业级应用,还是小型程序,掌握抽象类和接口的使用都至关重要。本文将通过详细的理论讲解、丰富的代码示例、直观的图片以及对比表格,帮助你深入理解Java抽象类和接口的本质与应用。
文章目录:
- 一、抽象类
-
- 1.什么是抽象类
- 2.抽象类语法
- 3.抽象类特征
-
- [3.1 抽象类不能实例化对象](#3.1 抽象类不能实例化对象)
- [3.2 抽象方法不能是private的](#3.2 抽象方法不能是private的)
- [3.3 抽象方法不能被final和static修饰,因为抽象方法要被子类重写](#3.3 抽象方法不能被final和static修饰,因为抽象方法要被子类重写)
- [3.4 抽象类必须被继承,并且继承后子类要重写父类的抽象方法,除非子类也是抽象类,用abstract修饰](#3.4 抽象类必须被继承,并且继承后子类要重写父类的抽象方法,除非子类也是抽象类,用abstract修饰)
- [3.5 抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类⼀定是抽象类](#3.5 抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类⼀定是抽象类)
- [3.6 抽象类中可以有构造⽅法,供⼦类创建对象时,初始化⽗类的成员变量](#3.6 抽象类中可以有构造⽅法,供⼦类创建对象时,初始化⽗类的成员变量)
- 4.抽象类的作用
- 二、接口
-
- 1.什么是接口?
- 2.语法规则
- 3.接口的使用
- 4.接口特性
-
- [4.1 接口是一种引用类型,但是不能直接new接口的对象](#4.1 接口是一种引用类型,但是不能直接new接口的对象)
- [4.2 接口中的方法会被默认为public abstract,其他修饰符会报错](#4.2 接口中的方法会被默认为public abstract,其他修饰符会报错)
- [4.3 接口中的方法不能在接口中实现,只能通过接口的类来实现](#4.3 接口中的方法不能在接口中实现,只能通过接口的类来实现)
- [4.4 重写接口方法时,不能使用默认的访问权限](#4.4 重写接口方法时,不能使用默认的访问权限)
- [4.5 接口中可以有变量,但他会被默认为public static final 变量](#4.5 接口中可以有变量,但他会被默认为public static final 变量)
- [4.6 接口中不能有静态代码块和构造方法](#4.6 接口中不能有静态代码块和构造方法)
- 5.实现多个接口
- 6.接口间的继承
- 7.接口使用实例
- 8.Clonable接口和深拷贝
-
- [8.1 Clonable接口](#8.1 Clonable接口)
- [8.2 浅拷贝](#8.2 浅拷贝)
- [8.3 深拷贝](#8.3 深拷贝)
- 9.抽象类和接口的区别
一、抽象类
1.什么是抽象类
在面对对象的概念中,所以对象都是通过类来描述的,但并不是所有的类都是用来描述对象的,如果一个类中没有包含足够的信息来描述一个具体的对象,这样的类就是抽象类
Dog类和Cat类都属于Animal类,但Dog()和Cat()方法没有实际的行为,可以将他们设计成
抽象方法
,包含抽象方法的类就是抽象类
。
2.抽象类语法
在Java中,被abstract
修饰的类称抽象类,抽象类中,被abstract
修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。
java
public abstract class Animal {
abstract public void eat();//抽象方法:被abstract修饰,没有方法体
public double show(){ //自己增加的方法
return show1;
}
protected double show1;//参数
}
3.抽象类特征
3.1 抽象类不能实例化对象
java
public abstract class Animal {
Animal animal = new Animal();
}

3.2 抽象方法不能是private的
java
public abstract class Animal {
abstract private void eat();//抽象方法:被abstract修饰,没有方法体
}

3.3 抽象方法不能被final和static修饰,因为抽象方法要被子类重写
java
abstract final void eat();
abstract public static void eat();

3.4 抽象类必须被继承,并且继承后子类要重写父类的抽象方法,除非子类也是抽象类,用abstract修饰
java
public abstract class Cat extends Animal {
@Override
public void eat(){
}
}
java
public abstract class Cat extends Animal {
@Override
public abstract void eat();
}
3.5 抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类⼀定是抽象类
3.6 抽象类中可以有构造⽅法,供⼦类创建对象时,初始化⽗类的成员变量
4.抽象类的作用
抽象类本身不能被实例化,只能创建子类,并且重写抽象方法,这就起到检验的作用
二、接口
1.什么是接口?
字面意思 :我们生活中的水龙头,插座,充电线都是有接口的,才能插上。
接口
就是公共的行为规范标准,在实现时,只要符合规范标准,就能通用
2.语法规则
接口的定义和类基本相同,将class
换成interface
关键字
java
public interface IShape {
public static final int SIZE = 100;//接口变量默认public static final
public abstract void test();//接口方法默认public abstract
}
【注意】
- 接口命名一般以大写字母
I
开头;- 接口不能被实例化;
3.接口的使用
类与接口之间是implements
的关系
java
public class 类名 implenments 接口名{
//...
}
这里建立一个IUSB接口和Mouse类
java
public interface IUSB {
void openDevice();
void closeDevice();
}
java
public class Mouse implements IUSB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
@Override
public void closeDevice() {
System.out.println("关闭鼠标");
}
}
4.接口特性
4.1 接口是一种引用类型,但是不能直接new接口的对象
java
public class TestUSB {
public static void main(String[] args) {
USB usb = new USB();
}
}

4.2 接口中的方法会被默认为public abstract,其他修饰符会报错
java
public interface USB {
private void openDevice();//private使用错误
void closeDevice();
}

4.3 接口中的方法不能在接口中实现,只能通过接口的类来实现
java
public interface USB {
//void openDevice();
void closeDevice(){
System.out.println("关闭USB设备");
}
}

4.4 重写接口方法时,不能使用默认的访问权限
java
public class Mouse implements USB{
@Override
public void openDevice() {
System.out.println("打开鼠标");
}
}

4.5 接口中可以有变量,但他会被默认为public static final 变量
java
public interface USB {
int susu = 250;//默认被final public static修饰
void openDevice();
void closeDevice();
}
4.6 接口中不能有静态代码块和构造方法
java
public interface USB {
public USB(){
}
{
}
int susu = 250;//默认被final public static修饰
void openDevice();
void closeDevice();
}

5.实现多个接口
一个类可以实现多个接口,这就是继承所做不到的
- 这里创建一个
Dog类
,可以让他实现多个接口
,如IRunning,ISwimming,IFlying。每个接口的抽象方法都有重写,否则必须设置为抽象类AIT + InS
快捷键重写
java
public class Dog extends Animal implements IRunning,ISwimming{
@Override
public void run() {
}
@Override
public void swim() {
}
}
狗:既能跑,又能游;
【注意】
有了接口之后,我们就不用注意具体类型,只需要关注这个类是否具备某种类型
6.接口间的继承
在Java中,类和类之间是单继承的,但一个类可以实现多个接口,接口与接口之间可以多继承
这段代码就继承了两个接口:游和跑
java
public class Dog extends Animal implements ISwimming,IRunning{
@Override
public void run() {
}
@Override
public void swim() {
}
}
7.接口使用实例
对象之间大小比较:
java
public class Student {
public String name;
public int score;
public Student (String name,int score){
this.name=name;
this.score=score;
}
@Override
public String toString() {
return super.toString();
}
}
java
public class Test {
public static void main(String[] args) {
Student s1 = new Student("小华",20);
Student s2 = new Student("小张",10);
System.out.println(s1>s2);
}
}

这样进行比较会报错,因为没有指定根据分数还是什么来比较,这样不太灵活,我们可以使用接口,如下:
使用Comparable接口
java
public class Student implements Comparable<Student>{
public String name;
public int age;
public Student (String name,int age){
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
if(this.age>o.age)
return 1;
else if(this.age == o.age)
return 0;
else
return -1;
}
}
java
public class Test {
public static void main(String[] args) {
Student s1 = new Student("小华",20);
Student s2 = new Student("小张",12);
//System.out.println(s1>s2);
if(s1.compareTo(s2)>0){
System.out.println("s1>s2");
}
}
}
使用Comparator接口
java
import java.util.Comparator;
public class AgeComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.age-o2.age;
}
}
java
public class Test {
public static void main(String[] args) {
Student s1 = new Student("小华",20);
Student s2 = new Student("小张",12);
AgeComparator ageComparator=new AgeComparator();
int ret = ageComparator.compare(s1,s2);
if(ret>0){
System.out.println("s1>s2");
}

如果是根据名字来比较的,就要看对应字母的大小
8.Clonable接口和深拷贝
8.1 Clonable接口
Java 中内置了⼀些很有⽤的接⼝,Clonable
就是其中之⼀.
Object 类
中存在⼀个clone⽅法
,调⽤这个⽅法可以创建⼀个对象的"拷⻉".但是要想合法调⽤clone
⽅法,必须要先实现Clonable接⼝,否则就会抛出CloneNotSupportedException
异常.
java
public class Person implements Cloneable{
public String name;
public int age;
public Person (String name,int age){
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
java
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException{
Person person1 = new Person("小华子",20);
Person person2 = (Person) person1.clone();//强制类型转换
System.out.println(person2);
}
}
受查异常/编译时异常
解决方法:
8.2 浅拷贝
java
class Money implements Cloneable{
public double money = 9.9;
java
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
java
lic class Test1 {
public static void main(String[] args) throws CloneNotSupportedException{
Person person1 = new Person("小华子",20);
Person person2 = (Person) person1.clone();
System.out.println(person1.m.money);
System.out.println(person2.m.money);
System.out.println("==============");
person2.m.money = 19.9;
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}


通过clone,我们只是拷⻉了Person对象。但是Person对象中的Money对象,并没有拷⻉。通过person2这个引⽤修改了m的值后,person1这个引⽤访问m的时候,值也发⽣了改变。这⾥就是发⽣了浅拷⻉。
8.3 深拷贝
java
class Money implements Cloneable{
public double money = 9.9;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Person implements Cloneable{
public String name;
public int age;
public Money m = new Money();
public Person (String name,int age){
this.name=name;
this.age=age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
//return super.clone();
Person tmp = (Person) super.clone();
tmp.m = (Money) this.m.clone();
return tmp;
}
}
java
public class Test1 {
public static void main(String[] args) throws CloneNotSupportedException{
Person person1 = new Person("小华子",20);
Person person2 = (Person) person1.clone();
System.out.println(person1.m.money);
System.out.println(person2.m.money);
System.out.println("==============");
person2.m.money = 19.9;
System.out.println(person1.m.money);
System.out.println(person2.m.money);
}
核心代码:
9.抽象类和接口的区别
抽象类中可以包含普通⽅法和普通字段,这样的普通⽅法和字段可以被⼦类直接使⽤(不必重写),
⽽接⼝中不能包含普通⽅法,⼦类必须重写所有的抽象⽅法.
No | 区别 | 抽象类(abstract) | 接口(interface) |
---|---|---|---|
1 | 结构组成 | 普通类+抽象方法 | 抽象方法+全局常量 |
2 | 权限 | 各种权限 | public |
3 | 子类使用 | 使用extends 关键字继承抽象类 |
使用implements 关键字实现接口 |
4 | 关系 | 一个抽象类可以实现若干接口 | 接口不能继承抽象类,可extends 继承多个父接口 |
5 | 子类限制 | 一个子类只能继承一个抽象类 | 一个子类可以实现多个接口 |
【总结】
在 Java 里,抽象类与接口是实现抽象编程的关键工具。抽象类融合普通类与抽象方法,可定义部分实现逻辑,权限灵活;接口由抽象方法和全局常量构成,成员权限默认 public 。子类继承抽象类用 extends ,实现接口用 implements 。关系上,抽象类能实现多个接口,接口可多继承。继承限制方面,子类单继承抽象类,却可多实现接口 。二者各有适用场景,抽象类适合提炼共性、留存部分实现;接口利于规范行为、实现多态解耦。合理运用它们,能让代码架构更清晰、可扩展与可维护,助力构建灵活且健壮的 Java 程序 。
