概述
接口就是一组规范(就像我们人间的法律一样),所有实现类都要遵守。
面向对象的精髓,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(比如C++、Java、C#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
接口的作用
· 为什么需要接口?接口和抽象类的区别?
接口就是比“抽象类”还“抽象”的“抽象类”,可以更加规范的对子类进行约束。全面地专业地实现了:规范和具体实现的分离。
接口是两个模块之间通信的标准,通信的规范。如果能把你要设计的模块之间的接口定义好,就相当于完成了系统的设计大纲,剩下的就是添砖加瓦的具体实现了。大家在工作以后,做系统时往往就是使用“面向接口”的思想来设计系统。
接口和实现类不是父子关系,是实现规则的关系。比如:我定义一个接口Runnable,Car实现它就能在地上跑,Train实现它也能在地上跑,飞机实现它也能在地上跑。就是说,如果它是交通工具,就一定能跑,但是一定要实现Runnable接口。
如何定义和使用接口
[访问修饰符] interface 接口名 [extends 父接口1,父接口2...]{
常量定义;
方法定义;
}
// 说明 : 这里面的访问修饰符只能是Public或者默认
定义接口的详细说明:
- 访问修饰符:只能是public或默认。
- 接口名:和类名采用相同命名机制。
- extends:接口可以多继承。
- 常量:接口中的属性只能是常量,总是:public static final 修饰。不写也是。
- 方法:接口中的方法只能是:public abstract。 省略的话,也是public abstract。
要点
- 子类通过implements来实现接口中的规范。
- 接口不能创建实例,但是可用于声明引用变量类型。
- 一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
- JDK1.8(不含8)之前,接口中只能包含静态常量、抽象方法,不能有普通属性、构造方法、普通方法。
JDK1.8(含8)后,接口中包含普通的静态方法、默认方法。
接口的使用
package TestInterface;
public interface Volant {
int FLY_HEIGHT = 100; //接口中的常量默认为public的静态final属性,相当于(public static final int FLY_HEIGHT)
/*public abstract */void fly();
}
interface Honest{
void helpHonest();
}
class GoodMan implements Honest{
@Override
public void helpHonest() {
System.out.println("好人善良乐于助人!");
}
}
class Plan implements Volant{
@Override
public void fly() {
System.out.println("飞机会飞!");
}
}
class Angel implements Volant,Honest{
@Override
public void fly() {
System.out.println("天使会飞");
}
@Override
public void helpHonest() {
System.out.println("天使也很善良!");
}
}
我们定义了Volant(能飞的)和Honest(善良)两个接口。分别根据我们现实生活中事物所具有的特性来实现接口的功能,方便大家理解。
分别在三个类中实现:
Plane(飞机)实现第一个接口中的fly方法;
GoodMan(好人)实现了Honest中的方法;
Angel(天使)同时具有飞和善良的特性,所以给她继承两个接口;
在接口中我们还定义了一个常量:FLY_HEIGHT来定义它们的飞行高度。最后这是我们的输出语句:
package TestInterface;
public class Test {
public static void main(String[] args) {
Angel a = new Angel();
a.fly();
a.helpHonest();
System.out.println(Volant.FLY_HEIGHT);
}
}
这和我们输出对象的方式是一致的,输出结果为:
这就实现了我们一个简单的接口;
接口新特性:
接下来我们来看看JAVA8之后给接口定义的一系列新特性:
JAVA8之前,接口里的方法要求全部是抽象方法。
JAVA8(含8)之后,以后允许在接口里定义默认方法和静态方法。
JDK8新特性_默认方法
Java 8及以上新版本,允许给接口添加一个非抽象的方法实现,只需要使用 default 关键字即可,这个特征又叫做默认方法(也称为扩展方法)。
默认方法和抽象方法的区别是抽象方法必须要被实现,默认方法不是。作为替代方式,接口可以提供默认方法的实现,所有这个接口的实现类都可以得到默认方法。
public class Test {
public static void main(String[] args) {
A a = new Test_A(); //在这里我们要注意的是对于接口初始化的对象是可以直接实例化类的
//这也可以看做面向接口编程,后期会大量使用
a.moren();
}
}
interface A {
default void moren(){
System.out.println("我是接口A中的默认方法!");
}
}
class Test_A implements A {
@Override
public void moren() {
System.out.println("Test_A.moren");
}
}
这样就实现了在接口类中默认方法的实现了!
JDK8新特性_静态方法
JAVA8以后,我们也可以在接口中直接定义静态方法的实现。这个静态方法直接从属于接口(接口也是类,一种特殊的类),可以通过接口名调用。
如果子类中定义了相同名字的静态方法,那就是完全不同的方法了,直接从属于子类。可以通过子类名直接调用。
package InterfaceStatic;
public class A {
public static void main(String[] args) {
B.staticMethod();
C.staticMethod();
}
}
interface B{
public static void staticMethod(){
System.out.println("我在接口类中定义了一个静态方法!");
}
}
class C implements B{
public static void staticMethod(){
System.out.println("我在类中ye定义了一个静态方法!");
}
}
输出结果:
接口中的多继承
接口支持多继承。和类的继承类似,子接口extends父接口,会获得父接口中的一切。
package InterfaceMultipleInherent;
public class Test {
public static void main(String[] args) {
D d = new D();
d.testA();
d.testB();
d.testC();
}
}
interface A{
void testA();
}
interface B{
void testB();
}
/*
* 接口可以多继承,接口C继承接口A和B
* */
interface C extends A,B{
void testC();
}
class D implements C{
@Override
public void testA() {
System.out.println("测试TestA");
}
@Override
public void testB() {
System.out.println("测试TestB");
}
@Override
public void testC() {
System.out.println("测试TestC");
}
}
输出结果:
后续我会持续更新java学习中几乎所有我们用到的知识点,如果对我的内容存在疑问就评论告诉我,我会第一时间回复。
满意的话请关注点赞支持!有任何需要私下解决的问题还请私信我!