Java接口介绍

Java接口介绍

接口(Interface),在Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface关键字来声明。Java接口是用于描述类所具有的方法集合,但并不提供实现这些方法的代码。它们被用来定义一个协议或者契约(Contract),使得各种不同的实现可以遵循相同的接口规则进行开发。

接口可以包括常量、方法签名和默认方法。常量在接口中被隐式的声明为public static final,而方法签名则是public abstract。默认方法是指在Java 8之后添加的一种方法,允许在接口中提供默认的实现方法,而不需要让实现类必须去覆盖该方法。

实现类必须通过implements关键字来实现接口,并且必须实现接口中声明的所有方法。由于Java不支持多继承,因此接口提供了一种机制来实现类似于多继承的特性。同时,接口还可以用于实现回调函数,以及在类与类之间传递消息等场景。

【在计算机编程中,契约(Contract)是一种规范或者协议,用于定义程序中组件之间的交互方式。可以将契约看作是一个约定,各个组件必须遵守该约定以便能够与其他组件进行交互。】

Java接口和类是两种不同的概念,它们有一些相同点,也有一些重要的区别。

相同点

都是Java中的语法结构;

都可以定义方法和常量;

都可以被继承。

不同点

类可以提供方法的具体实现,而接口只能定义方法的签名,不能提供具体实现;

一个类可以实现多个接口,但只能继承一个父类;

接口中的变量隐式的是public static final类型,并且必须进行初始化赋值,而类中的变量则不需要;

接口中的方法默认是public abstract类型,不能有具体实现;而在类中,可以定义public、protected、private类型的方法,并且可以有具体实现;

接口中还可以定义default方法和static方法,在Java 8之后添加,用于提供默认实现和静态方法等功能。

在Java中,方法的签名(Signature)包括方法名和参数列表。方法名用于标识方法的名称,参数列表则描述了方法需要接收的参数类型和数量,用于唯一标识一个方法。方法签名不包含方法返回值类型和修饰符。

例如,以下两个方法的签名是不同的:

java

public void print(String message) {}

public void print(int message) {}

虽然它们都有相同的方法名print,但是它们的参数列表不同,一个接收一个字符串参数,一个接收一个整数参数,因此它们有不同的方法签名。

Java接口的组成

Java使用接口程序的组成通常包括以下几个部分:

接口定义:使用interface关键字来定义接口,其中包含了方法签名和常量等元素;

实现类定义:实现类通过implements关键字来实现接口,并提供具体的实现代码;

调用者代码:调用者可以直接使用接口类型来引用任意一个实现类对象,并调用接口中定义的方法。

以下是一个示例,本例将接口、实现类和调用测试类定义在同一个Java文件中:

//接口Animal
interface Animal {
    void eat();
}

//实现类Cat
class Cat implements Animal {
    public void eat() {
        System.out.println("Cat is eating.");
    }
}

//调用者(测试类)代码
public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.eat(); // 打印输出:Cat is eating.
    }
}

【在同一个Java文件中,只能有一个public类(或接口),这个类的名称必须与文件名相同。】

上面的例子将接口、实现类和调用测试类定义在同一个Java文件中,但通常不建议这样做,因为这会导致代码可读性下降,增加代码维护难度。我们还是应该将接口、实现类和调用者测试代码类分别放置在独立的Java文件中。

这种保存方式符合Java的模块化设计思想,有利于代码的组织和管理。同时,这也是Java编译器所要求的规定,如果没有按照这种方式保存文件,就会导致编译错误。

需要注意的是,当实现类较少时,也可以将其与接口定义保存在同一个.java文件中。这种做法虽然不太规范,但在某些情况下可以提高代码的可读性和方便性。然而,调用者代码仍然应该单独放在一个.java文件中,以确保程序的可维护性和扩展性。

下面是一个简单的示例,演示了Java使用接口程序的基本结构:

本示例由三个文件构成

Shape.java文件:

// 定义接口
public interface Shape{
    public double getArea();
}

 Circle.java文件:

// 实现Circle类
public class Circle implements Shape{
    private double radius;

    public Circle(double r){
        radius = r;
    }

    // 实现接口的方法
    public double getArea(){
        return Math.PI * radius * radius;
    }
}
// 调用者代码
public class Test{
    public static void main(String[] args){
        Shape s = new Circle(2.0);
        double area = s.getArea();
        System.out.println("圆面积:" + area); //圆面积:12.566370614359172
    }
}

在上面的示例中,我们首先定义了一个Shape接口,它包含一个getArea()方法,用于计算形状的面积。然后我们定义了Circle类,它实现了Shape接口,并提供了自己的getArea()实现。最后,我们在Test类中创建了一个Circle实例,并将其赋给一个Shape类型的变量s,然后调用s的getArea()方法来计算圆形的面积。

这个示例展示了Java使用接口程序的基本结构,其中包括了接口定义、实现类定义和调用者代码三个部分。通过使用接口,我们可以方便地对不同的实现类进行管理和扩展,并且保障程序的稳定性和可维护性。

下面是对上面例子的改进,添加Rectangle部分,修改Test。

本示例是对前一个示例的改进,添加了Rectangle文件,修改了Test文件,由四个文件构成:

定义接口的Shape.java文件和实现Circle类的文件和前面相同。

Rectangle.java类文件: 

// 实现 Rectangle类
public class Rectangle implements Shape{
    private double width;
    private double height;

    public Rectangle(double w, double h){
        width = w;
        height = h;
    }

    // 实现接口的方法
    public double getArea(){
        return width * height;
    }
}

Test.java文件修改为:

// 调用者代码
public class Test{
    public static void main(String[] args){
        Shape s1 = new Circle(2.0);
        Shape s2 = new Rectangle(3.0, 4.0);

        System.out.println("圆面积:" + s1.getArea()); //圆面积:12.566370614359172
        System.out.println("矩形面积:" + s2.getArea()); //矩形面积:12.0    }
}

接口继承

在Java中,接口可以像类一样继承其他接口,这种机制称为接口的继承。接口继承基本语法如下:

public interface SubInterface extends SuperInterface {

    // 子接口定义的方法

}

其中SubInterface是子接口,SuperInterface是父接口。子接口可以继承一个或多个父接口,多个父接口之间使用逗号,分隔。

子接口从父接口中继承了所有抽象方法,并且可以在自身中添加新的抽象方法。子接口也可以重写父接口中的默认方法和静态方法,并且可以使用super关键字来调用父接口中的默认方法。

例如,以下是一个接口继承的例子:

Animal.java文件:

// Animal接口
public interface Animal {
    void eat();
}

Cat.java文件:

//Cat接口继承了Animal接口
public interface Cat extends Animal {
    void meow();
}

PersianCat.java文件:

public class PersianCat implements Cat {
    public void eat() {
        System.out.println("The cat is eating...");
    }

    public void meow() {
        System.out.println("Meow~");
    }
}

TestA.java文件:

// 调用者(测试)代码
public class TestA{
    public static void main(String[] args){
        PersianCat cat = new PersianCat();
        cat.eat(); // The cat is eating...
        cat.meow(); // Meow~
    }
}

在上述例子中,Animal接口定义了eat()方法,Cat接口继承了Animal接口并新增了meow()方法,PersianCat类实现了Cat接口,并且必须实现父接口Animal中的抽象方法eat()和新增的抽象方法meow()。

接口(interface)和抽象类(abstract class)的异同

【关于抽象类(abstract class)可参见https://mp.csdn.net/mp_blog/creation/editor/130618011

接口(interface)和抽象类(abstract class)都是Java中用于实现多态性的机制。它们都可以被继承,并且都可以包含抽象方法,但它们之间也存在着很多不同之处。下面我们来看一下它们之间的异同。

1.抽象类可以包含非抽象方法和成员变量,而接口只能包含常量和抽象方法。换句话说,抽象类既可以包含具体的实现,也可以包含抽象的行为,而接口只能定义抽象的行为。

2.子类只能继承一个抽象类,但是可以实现多个接口。这是因为Java语言本身不支持多重继承,但是子类可以通过实现多个接口来获得多个行为的实现。如果一个类既要继承其他类,又要实现多个接口,那么就必须使用抽象类来作为基类。

3.抽象类可以包含构造方法,而接口不能包含构造方法。这是因为接口没有实例化的概念,所以它也没有构造方法的需求。

4.抽象类的访问权限可以是public、protected或默认的,而接口的访问权限必须是public。这是因为接口是一种公共的契约,任何类都可以实现它,所以它必须是公开的。

5.抽象类可以用来定义模板方法,而接口则不能。模板方法是一种设计模式,在抽象类中定义了一个算法的框架,然后由子类去实现具体的步骤。

总的来说,我们可以这么理解接口和抽象类的区别:抽象类是对事物的抽象,既包含行为又包含状态;接口是对行为的抽象,只定义了行为规范,没有状态的表示。

在使用时,我们应该根据具体的需要选择使用接口还是抽象类。如果我们需要定义一些基本的行为和属性,并且希望子类能够共享这些基础功能,那么就可以使用抽象类;如果我们需要定义一些行为规范,但不关心实现细节,那么就可以使用接口。

附录、进一步学习了解

java 接口 详解-阿里云开发者社区

java接口详解-腾讯云开发者社区-腾讯云

猜你喜欢

转载自blog.csdn.net/cnds123/article/details/130618885
今日推荐