目录
(1)接口:
Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。它定义了一组方法(可以带有默认实现)供实现了该接口的类来实现。接口本身不包含任何实现,只定义了方法的签名。
按照我的理解就是,它很像继承的父类里面有一些方法(很笼统的一个概念,没有具体的实现,如果子类继承后像要丰富这些方法就要重写。但是父类也不是很全面的将子类所有的方法都包含了,肯定有一些特别的方面,就比方一个Animal类,里肯定有会eat和sleep的方法叭,但是有一些小动物有的会飞,有的会游泳,我们难道要在创建两个类去添加这两个方法嘛,然后再让这些小动物去分别继承这些类嘛,这也太麻烦了,这时候就引出来接口的概念,它更像是方法的集合,将这些方法以一个笼统的概念去描述,当有的类符合这写方法就可以(继承)调用这些接口。然后再类里面去重写去细致的描绘。)
举个例子,假设我们有一个图形绘制系统,我们可以定义一个名为 Drawable
的接口,来表示可以被绘制的对象,然后让各种图形类(如圆、矩形、三角形等)实现这个接口,以确保它们都具备了绘制的能力。
// 定义一个绘制接口
interface Drawable {
void draw(); // 绘制的方法
}
// 圆类实现了绘制接口
class Circle implements Drawable {
@Override
public void draw() {
System.out.println("绘制一个圆");
}
}
// 矩形类实现了绘制接口
class Rectangle implements Drawable {
@Override
public void draw() {
System.out.println("绘制一个矩形");
}
}
// 测试
public class Main {
public static void main(String[] args) {
Drawable circle = new Circle();
Drawable rectangle = new Rectangle();
circle.draw(); // 输出:绘制一个圆
rectangle.draw(); // 输出:绘制一个矩形
}
}
在这个例子中,接口 Drawable
定义了一个 draw
方法,任何实现了这个接口的类都必须提供 draw
方法的具体实现。类 Circle
和 Rectangle
都实现了 Drawable
接口,因此它们都必须实现 draw
方法。这样我们就能够使用多态的方式来调用这些不同的图形对象的 draw
方法,实现了一种统一的调用方式。
(2)接口中的注意事项:
-
接口方法是抽象的: 接口中的方法都是抽象的,即只有方法的声明而没有实现。实现接口的类必须提供方法的具体实现。
-
实现接口的类必须实现接口中的所有方法: 如果一个类实现了一个接口,那么它必须实现该接口中定义的所有方法,否则它必须声明为抽象类。
-
接口可以被多继承: 一个类可以实现多个接口,从而达到多继承的效果。
-
接口可以包含常量: 接口可以包含常量,这些常量默认为
public static final
。 -
接口中不能包含实例变量: 接口中只能包含常量,不能包含实例变量。
-
接口可以被扩展: 接口可以继承其他接口,从而可以形成接口的继承关系。
-
接口是一种约定: 接口定义了类的一种契约,实现了接口的类必须遵循接口中定义的方法。
-
接口和抽象类的选择: 如果类在逻辑上是一个子类,同时它需要继承另一个类,那么就应该选择抽象类。如果类不需要继承另一个类,但是需要与其他类共享方法签名,那么就应该选择接口。(方法签名是指方法的声明部分,包括方法的名称、参数类型和参数顺序,但不包括方法的具体实现和返回类型。方法签名用于识别和区分不同的方法,即使方法具体的实现不同,只要方法签名相同,编译器和虚拟机会将它们视为同一个方法。)
(3)接口中的成员特点:
成员变量:
-
默认为
public static final
:接口中的成员变量默认被隐式地声明为public static final
,这意味着它们是公共、静态和不可变的。在接口中声明的成员变量必须在声明时进行初始化,且不能被修改。 -
必须初始化:接口中声明的成员变量必须在声明时进行初始化,或者在接口的构造方法中进行初始化。因为它们是
public static final
的,所以它们的值在编译时就已经确定,不能在运行时修改。 -
默认为常量:由于成员变量是
public static final
的,它们被视为接口的常量,通常使用全大写的命名规范。例如:int MAX_COUNT = 10;
-
不是实例变量:接口中的成员变量是类级别的,而不是实例级别的。即使实现了接口的类创建多个实例,它们共享相同的接口成员变量。
-
可以被继承:如果一个接口继承了另一个接口,它会继承父接口的所有成员变量。
-
默认为公共访问权限:由于接口中的成员变量默认是
public
的,因此它们可以被实现了接口的类的任何地方访问,甚至在外部也可以通过接口名称访问。
public interface MyInterface {
int MAX_COUNT = 10;
String DEFAULT_NAME = "Default";
void doSomething();
}
成员方法:
-
默认为
public abstract
:接口中的成员方法默认被隐式地声明为public abstract
,这意味着它们是公共的抽象方法。实现接口的类必须提供这些方法的具体实现。 -
没有方法体:接口中的方法没有具体的方法体,只有方法的声明。具体的方法实现需要在实现接口的类中完成,与普通的类方法不同,接口中的方法不能包含方法体,即不能有花括号
{}
内的代码块。 -
自动为抽象方法:由于接口中的方法默认是抽象的,因此在接口中可以省略
abstract
关键字。 -
不能被
private
或final
修饰:接口中的方法不能使用private
或final
修饰,因为接口的方法必须在实现类中进行具体实现。 -
实现接口的类必须提供方法实现:实现接口的类必须提供接口中定义的所有方法的具体实现,否则这个类必须声明为抽象类。
-
可以有默认方法和静态方法:从Java 8开始,接口中可以包含默认方法(带有方法体的方法,使用
default
关键字声明)和静态方法(使用static
关键字声明)。默认方法提供了接口方法的默认实现,而静态方法在接口层级上提供了一种公用的工具方法。
public interface MyInterface {
void doSomething();
int calculate(int a, int b);
}
在这个例子中,doSomething
和 calculate
都是接口MyInterface
的成员方法,它们隐式地具有public abstract
修饰符,需要在实现了MyInterface
的类中提供具体实现。
(4)接口、类之间的关系:
类和类之间的关系 :
-
继承关系(Inheritance):一个类可以继承另一个类的属性和方法。继承关系中,被继承的类称为父类(基类),继承的类称为子类(派生类)。子类可以重写父类的方法,扩展或修改功能。使用关键字
extends
来建立继承关系。 -
实现关系(Implementation):一个类可以实现一个接口,需要提供接口中定义的所有方法的具体实现。接口是一种规范,定义了一组方法的签名。使用关键字
implements
来建立实现关系。 -
关联关系(Association):表示不同类之间的联系,一个类可以使用另一个类的对象作为成员变量。关联关系可以是双向的,也可以是单向的。关联关系可以表示整体与部分之间的关系。
-
依赖关系(Dependency):一个类在某个方法中使用了另一个类的对象,但不持有该对象。依赖关系是一种弱关系,一个类的变化不会影响到另一个类。
-
聚合关系(Aggregation):表示整体与部分之间的关系,整体对象包含部分对象。聚合关系中,整体对象和部分对象的生命周期可以独立存在。
-
组合关系(Composition):是一种更强的聚合关系,表示整体对象的生命周期和部分对象关联,整体对象包含部分对象。部分对象不能独立存在。
呜呜呜,这里就不说啦!我还不是太了解,就知道前两个!
类和接口之间的关系 :
1.实现关系(Implementation):一个类可以实现一个或多个接口。实现关系用于指定类将如何提供接口中定义的方法。通过实现接口,类必须提供接口中所有方法的具体实现。使用关键字 implements
建立实现关系。
在实现时,如果不同的接口里面有重名的方法,我们再实现接口的时候只需要重写其中一个重名的方法!
2.多重继承:通过实现多个接口,一个类可以达到类似多重继承的效果。多重继承是指一个类继承了多个父类的属性和方法。在Java中,类只支持单继承,但一个类可以实现多个接口,从而获得多个接口中方法的实现。
接口和接口之间的关系:
继承关系(接口继承接口): 一个接口可以继承自另一个或多个接口,这种继承关系称为接口的继承。继承的语法使用 extends
关键字。继承可以使子接口获得父接口中定义的方法,从而形成更复杂的接口层次结构。
注意:继承后的子接口要重写父接口的所有抽象方法(包括父亲的父亲~)
(5)补充:
jdk7以前接口里面只有抽象方法,jdk8以后接口里面可以定义有方法体的方法,jdk9后接口里面可以写一些私有方法
jdk8中的方法,是需要关键default关键字来修饰的
//格式
public default 返回值类型 方法名(参数列表){
//方法
}
这里面的方法不是抽象的,继承后子类可以重写也可以不重写,如果重写的话,需要去掉default关键字。另外值的一提的就是如果一个类实现了多个接口并且子接口里面有相同名字的默认方法,子类就必须对该方法进行重新写。
接口里面的静态方法:(没有重写!)
//格式
public static 返回值类型 方法名(参数列表){
//方法
}
静态方法只能用接口名进项调用,不能通过实现类名(继承的)或者对象名进行调用。public可以省但是static不可以省略。
jdk9私有方法:
方式1 为默认方法服务
private 返回值类型 方法名(参数列表){
//方法
}
方式2 为静态方法进行服务的
private static 返回值类型 方法名(参数列表){
//方法
}