![cover](https://img-blog.csdnimg.cn/img_convert/1f20816e15694cf3b56262c1f87e2a14.png)
Java接口介绍
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.抽象类可以用来定义模板方法,而接口则不能。模板方法是一种设计模式,在抽象类中定义了一个算法的框架,然后由子类去实现具体的步骤。
总的来说,我们可以这么理解接口和抽象类的区别:抽象类是对事物的抽象,既包含行为又包含状态;接口是对行为的抽象,只定义了行为规范,没有状态的表示。
在使用时,我们应该根据具体的需要选择使用接口还是抽象类。如果我们需要定义一些基本的行为和属性,并且希望子类能够共享这些基础功能,那么就可以使用抽象类;如果我们需要定义一些行为规范,但不关心实现细节,那么就可以使用接口。
附录、进一步学习了解
![Logo](https://devpress.csdnimg.cn/79de2bf0b7994defa4242ef90d5513fa.jpg)
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)