• Java接口和抽象类的区别


    接口和抽象类是面向对象编程中的重要概念,它们都提供了一种方式,使得我们可以定义一个模板,并让其他类实现或继承这个模板。尽管他们有一些相似之处,但接口和抽象类在Java和其他面向对象编程语言中有一些关键的区别。

    基本定义和使用:

    ○ 抽象类:抽象类是一个不能被实例化的类,它用来定义抽象方法,这些抽象方法没有实现(没有方法体)。抽象类不能直接被实例化,但可以被继承。子类必须实现(或继承)所有父类的抽象方法。
    ○ 接口:接口是一个完全抽象的类,它只包含抽象方法。接口不能被实例化,也不能有构造器。任何实现接口的类必须实现接口中的所有方法。

    实现:

    ○ 抽象类:一个类可以实现一个或多个接口,但只能继承一个抽象类。这是因为Java不支持多重继承。
    ○ 接口:一个类可以实现一个或多个接口。

    默认行为:

    ○ 抽象类:抽象类可以包含非抽象方法,即有方法体的方法。子类继承抽象类时,可以继承这些非抽象方法,除非子类自己重写了这些方法。
    ○ 接口:接口不能包含非抽象方法。所有在接口中声明的方法都必须是抽象的。

    设计目的:

    ○ 抽象类:通常用于表示一个抽象的概念或者一个基础类别,比如“动物”或者“车辆”。它提供了部分实现,可以添加更多的具体细节。
    ○ 接口:通常用于定义一个契约或者一组方法,它们必须被实现。接口使你能无视实现细节,只关注提供哪些方法。例如,一个“图形”接口可能定义了所有图形应该有的方法,如“绘制”,“移动”等。

    其他区别:

    ○ 访问控制:在Java中,抽象类可以有public、protected和default这三种访问权限,而接口只有public一种访问权限。
    ○ 使用场景:如果预计到会有很多不同的实现,并且需要定义很多公共的行为和特性,那么使用接口是一个好选择。如果只需要定义一个基础的类别,并允许子类有一些不同的实现方式,那么使用抽象类更合适。
    接口中的属性默认为 public static final,抽象类中的属性可以是任何访问修饰符。
    接口中的方法默认为 public abstract,抽象类中的方法可以是任何访问修饰符。

    构造函数:

    ○ 接口不能有构造函数,因为接口无法被实例化。
    ○ 抽象类可以有构造函数,并且可以被实例化,用于创建子类的实例。

    总的来说,接口和抽象类都是面向对象编程的重要部分,它们都有各自的用途和优点。选择使用哪一个取决于你的具体需求和设计考虑。

    接口

    在 Java 中,接口(Interface)是一种特殊的类类型,它定义了一个对象的行为和功能,但没有实现。接口可以看作是一组方法声明的集合,其中每个方法都是抽象的,没有方法体。接口可以被类实现,而类实现接口后,必须实现接口中所有的方法。

    以下是关于 Java 接口的一些要点:

    1. 定义接口:使用 interface 关键字来定义一个接口。接口中只能包含常量、抽象方法、默认方法和静态方法。
    2. 常量:接口中的常量必须使用 public static final 修饰符,且必须初始化赋值。常量名通常使用大写字母。
    3. 抽象方法:接口中的抽象方法只有方法签名,没有方法体,必须使用 public abstract 修饰符声明。实现类必须实现接口中所有的抽象方法。
    4. 默认方法:接口中的默认方法提供了一个默认实现,可以直接在接口中进行方法的实现,但是该方法必须使用 default 关键字进行修饰。默认方法可以被覆盖,也可以被实现类继承或调用。
    5. 静态方法:接口中的静态方法必须使用 public static 修饰符进行声明。静态方法只能使用接口名进行访问,不能使用实现类的引用或对象进行访问。
    6. 继承接口:接口可以继承一个或多个接口,使用 extends 关键字来进行声明。继承接口后,子接口可以拥有父接口中的所有方法和常量。
    7. 实现接口:类可以通过 implements 关键字来实现接口,实现类必须实现接口中的所有抽象方法。一个类可以同时实现多个接口,接口之间使用逗号隔开。
    8. 接口的作用:接口主要用于定义行为和功能,提供了一种代码复用和扩展的方式。通过接口,我们可以定义通用的行为规范,而具体实现则由实现类来完成。

    下面是一个使用接口的示例代码:

    interface Animal {
        String name = "Animal";
        void sound();
        default void eat() {
            System.out.println(name + " is eating.");
        }
    }
    
    class Cat implements Animal {
        private String name;
    
        public Cat(String name) {
            this.name = name;
        }
    
        public void sound() {
            System.out.println(name + " says Meow!");
        }
    }
    
    class Dog implements Animal {
        private String name;
    
        public Dog(String name) {
            this.name = name;
        }
    
        public void sound() {
            System.out.println(name + " says Woof!");
        }
    
        public void eat() {
            System.out.println(name + " is eating bones.");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Animal cat = new Cat("Tom");
            cat.sound(); // 输出:Tom says Meow!
            cat.eat(); // 输出:Animal is eating.
    
            Animal dog = new Dog("Max");
            dog.sound(); // 输出:Max says Woof!
            dog.eat(); // 输出:Max is eating bones.
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在上面的例子中,Animal 是一个接口,定义了 sound() 抽象方法和 eat() 默认方法。Cat 和 Dog 分别实现了 Animal 接口,并实现了 sound() 方法和自己的 eat() 方法。

    通过接口,我们可以定义通用的行为规范,而具体的实现则由实现类来完成。接口提供了一种代码复用和扩展的方式,在实现多态和解耦合方面非常有效。

    抽象类

    在Java中,抽象类(Abstract Class)是一种特殊的类,它用于定义具有共同特征和行为的对象的模板。抽象类不能实例化,只能被继承,并且可以包含抽象方法、具体方法和成员变量。

    以下是抽象类的一些要点:

    1. 定义抽象类:使用 abstract 关键字将一个类声明为抽象类。抽象类可以包含抽象方法和具体方法。
    2. 抽象方法:抽象方法是没有实现的方法,它只有方法签名,没有方法体。抽象方法使用 abstract 关键字进行声明,必须在抽象类中进行定义。抽象方法用于表示一种行为,具体的实现由子类提供。
    3. 子类继承抽象类:子类使用 extends 关键字继承抽象类。如果一个类继承了抽象类,那么它必须实现抽象类中的所有抽象方法,除非子类自己也声明为抽象类。
    4. 实例化抽象类:抽象类不能被直接实例化,即不能使用 new 关键字来创建抽象类的对象。但是可以通过多态的方式,使用抽象类的引用指向其具体子类的对象。
    5. 具体方法:抽象类可以包含具体方法,即已经实现的方法。子类继承抽象类后,可以直接使用父类的具体方法。
    6. 构造方法:抽象类可以有构造方法,但是由于抽象类不能被实例化,构造方法主要是用于被子类调用。
    7. 成员变量:抽象类可以包含各种类型的成员变量,包括私有变量、受保护变量等。
    8. 抽象类的作用:抽象类主要用于定义一组相关的类的通用特征和行为,提供了一种模板设计的思想,可以通过继承抽象类来实现代码的复用和扩展。

    下面是一个使用抽象类的示例代码:

    public abstract class Animal {
        private String name;
    
        public Animal(String name) {
            this.name = name;
        }
    
        public abstract void sound();
    
        public void eat() {
            System.out.println(name + " is eating.");
        }
    }
    
    public class Cat extends Animal {
        public Cat(String name) {
            super(name);
        }
    
        public void sound() {
            System.out.println("Cat: Meow!");
        }
    }
    
    public class Dog extends Animal {
        public Dog(String name) {
            super(name);
        }
    
        public void sound() {
            System.out.println("Dog: Woof!");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Animal cat = new Cat("Tom");
            cat.sound(); // 输出:Cat: Meow!
            cat.eat(); // 输出:Tom is eating.
    
            Animal dog = new Dog("Max");
            dog.sound(); // 输出:Dog: Woof!
            dog.eat(); // 输出:Max is eating.
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    在上面的例子中,Animal 是一个抽象类,定义了 sound() 抽象方法和 eat() 具体方法。Cat 和 Dog 分别继承自 Animal,并实现了 sound() 方法。

    通过抽象类,我们可以定义一些通用的特征和行为,并且通过子类来提供具体的实现。抽象类可以作为代码复用和扩展的基础。

    Java类是单继承的和实现多个接口的原因

    Java不支持多继承,但是是支持多实现的,也就是说,同一个类可以同时实现多个接口。
    Java类是单继承的,主要是为了简化语言设计和避免复杂性和冲突。而Java接口可以多继承,以实现更灵活和可复用的代码。这种设计平衡了面向对象编程的可扩展性和易用性

    在面向对象编程中,继承是一种机制,允许一个类从另一个类继承属性和方法。多继承指的是一个类可以从多个父类继承属性和方法。
    Java之所以不支持多继承,是为了避免多继承可能带来的问题和复杂性,同时保持语言的简洁和易用性。Java采用了单继承的模型,一个类只能直接继承自一个父类。这种限制确保了继承关系的清晰和可控性。
    为了解决多继承的一些问题,Java引入了接口(interface)的概念,通过实现接口可以达到类似多继承的效果。一个类可以实现多个接口,从而拥有接口中定义的方法。接口提供了一种更灵活的方式来实现代码的复用和扩展。

    Java类是单继承的,这是为了避免引入多继承可能导致的复杂性和冲突。
    当一个Java类继承另一个类时,它只能继承自单个父类。这是因为Java使用了单继承模型,即一个类只能有一个直接父类。这种设计决策主要是出于以下原因:

    1. 避免菱形继承问题(Diamond Problem):如果Java支持多继承,那么当一个类继承自多个父类,而这些父类又共同继承自同一个父类时,就会产生菱形继承问题。这会增加编译器和运行时解析继承关系的复杂性,也容易导致冲突。
    2. 简化语言规范和设计:单继承使得Java语言规范更加简洁和一致。它使得Java的类型层次结构和继承关系更加清晰,并且更易于理解、推理和维护。
      相比之下,Java接口可以多继承。一个接口可以继承自多个接口,这种机制称为多继承接口。这是为了允许类实现多个不同的接口,从而实现更灵活和可复用的代码。
      通过使用接口多继承,可以在类中实现多个不同的行为集合。这样,类可以根据需要选择性地实现不同的接口,并在实现过程中获得各个接口的方法和特性。

    接口是常量值和方法定义的集合。接口是一种特殊的抽象类。
    java类是单继承的。classB Extends classA
    java接口可以多继承。Interface3 Extends Interface0, Interface1, interface……
    不允许类多重继承的主要原因是,如果A同时继承B和C,而b和c同时有一个D方法,A如何决定该继承那一个呢?
    但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。

    首先说明java多实现的背景:
    c++中的指针和多重继承易产生安全问题。子类有多个父类,父类又有其父类,继承树很复杂,方法重写和构造易混乱,代码也不易维护。java吸取教训,采用了单继承多实现的方式。
    显然这种bug,接口编写者不会发现,只有程序员在写实现类时,首先就会报错。
    解决方法:实现类里写个内部类,分别实现两个接口。
    补:java规范里,方法名+参数(不含返回值类型)唯一确定一个方法。
    参考技术A一个类可以实现无限个接口,但仅能从一个抽象(或任何其他类型)类继承,从抽象类派生的类仍可实现接口,从而得出接口是用来解决多重继承问题的。

  • 相关阅读:
    【算法 - 动态规划】最长回文子序列
    LeetCode 84.柱状图中最大的矩形
    C#实现访问OPC UA服务器
    #力扣:26. 删除有序数组中的重复项@FDDLC
    5-2 Pytorch中的模型层layers
    Spring的资源管理(Resource)
    Redis 6.0源码学习 String类型
    代码臃肿已成常态:99% 计算机资源都被浪费掉了
    锐龙r7 6800u和i5 12500h选哪个好 r76800u和i512500h对比
    【LeetCode每日一题】——130.被围绕的区域
  • 原文地址:https://blog.csdn.net/Fireworkit/article/details/134329382