概念
一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法。
特点
就像一个类一样,一个接口也能够拥有方法和属性,但是在接口中声明的方法默认是抽象的。(即只有方法标识符,而没有方法体)。
接口指明了一个类必须要做什么和不能做什么,相当于类的蓝图。
一个接口就是描述一种能力,比如“运动员”也可以作为一个接口,并且任何实现“运动员”接口的类都必须有能力实现奔跑这个动作(或者implement move()方法),所以接口的作用就是告诉类,你要实现我这种接口代表的功能,你就必须实现某些方法,我才能承认你确实拥有该接口代表的某种能力。
如果一个类实现了一个接口中要求的所有的方法,然而没有提供方法体而仅仅只有方法标识,那么这个类一定是一个抽象类。(必须记住:抽象方法只能存在于抽象类或者接口中,但抽象类中却能存在非抽象方法,即有方法体的方法。接口是百分之百的抽象类)
一个JAVA库中接口的例子是:Comparator 接口,这个接口代表了“能够进行比较”这种能力,任何类只要实现了这个Comparator接口的话,这个类也具备了“比较”这种能力,那么就可以用来进行排序操作了。
抽象性
接口中的方法默认是抽象的(Java 8 之前),只有方法签名,没有方法体。例如:
interface Animal {
void eat(); // 抽象方法,默认是 public abstract
}
要求实现该接口的类必须为这些抽象方法提供具体实现,从而保证了代码的规范性和一致性。
常量定义
接口中可以定义常量,这些常量默认是 public static final
类型的。例如:
interface MathConstants {
double PI = 3.14159;
}
意味着这些常量是全局可访问的、静态的(可以通过接口名直接访问),并且一旦定义就不能被修改。
多实现
一个类可以实现多个接口,这为类提供了更多的灵活性和功能组合的可能性,一定程度上弥补了 Java 单继承的限制。例如:
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("Duck is flying.");
}
@Override
public void swim() {
System.out.println("Duck is swimming.");
}
}
为什么要用接口
实现多态
- 多态表现:多态允许不同的对象通过相同的接口进行调用,从而在运行时根据实际对象类型执行不同的行为。这大大增强了代码的灵活性和可扩展性。
- 代码示例:以图形绘制系统为例,定义一个
Shape
接口,其中包含draw
方法,不同的图形类(如Circle
、Rectangle
)实现该接口并提供各自的绘制逻辑。
interface Shape {
void draw();
}
class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
public class Main {
public static void main(String[] args) {
Shape circle = new Circle();
Shape rectangle = new Rectangle();
circle.draw();
rectangle.draw();
}
}
通过Shape
接口,我们可以编写通用的代码来处理不同的图形对象,而不需要关心具体是哪种图形。当需要添加新的图形时,只需实现Shape
接口即可。
解耦代码
- 降低依赖:接口可以将调用者和实现者分离,使得模块之间的依赖关系更加松散。调用者只需要依赖接口,而不需要关心具体的实现类。
- 代码示例:在一个电商系统中,定义一个
Payment
接口,不同的支付方式(如CreditCardPayment
、PayPalPayment
)实现该接口。
interface Payment {
void pay(double amount);
}
class CreditCardPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paying $" + amount + " with credit card");
}
}
class PayPalPayment implements Payment {
@Override
public void pay(double amount) {
System.out.println("Paying $" + amount + " with PayPal");
}
}
class Order {
private Payment payment;
public Order(Payment payment) {
this.payment = payment;
}
public void processOrder(double amount) {
payment.pay(amount);
}
}
public class Main {
public static void main(String[] args) {
Payment creditCardPayment = new CreditCardPayment();
Order order1 = new Order(creditCardPayment);
order1.processOrder(100.0);
Payment paypalPayment = new PayPalPayment();
Order order2 = new Order(paypalPayment);
order2.processOrder(200.0);
}
}
Order
类只依赖于Payment
接口,而不依赖具体的支付实现类。这样,当需要添加新的支付方式时,只需要实现Payment
接口,而不需要修改Order
类的代码。
笔记
接口用interface定义
接口都是抽象方法
接口中public abstract 修饰的protected. private不可以因为要继承
接口中的质有变量都是被static final修饰的 全部都是和类相关的属性
接口没有构造方法,使用多态
实现接口用implements关键字,实现接口必须要实现接口中所有的方法,如果不实现接口中的所有方法,那么该类为抽象类
接口与类之间是实现关系实现接口用implements关键字,可以支持多实现public class AnimalIntImpl implements AnimalInt,B,C
接口和接口之间是继承关系使用extends关键字表示继承,可以实现多继承public interface ArimalInt extends B,C
类可以既实现接口同时继承其他类public class AnimalIntImpl extends Demo implements AnimalInt
Java8之后,接口中可以有默认方法用defǎult修饰即可