Java学习笔记(疯狂Java讲义第三版)——接口

Java语言中的接口

通过抽象类,可以为类的定义建立模板。规定该继承抽象类的类,应该具有哪些方法和哪些成员变量。
但是,只是规定了应该有哪些成员变量和方法,而对于成员变量来说,取值可以根据继承抽象类的子类在创建对象的时候自由设置,即没有对成员变量进行严格的数值要求。
即抽象类仅仅起到了模板的作用,也就是规定了继承抽象类的类应该具有哪些成员变量和方法,具体的细节和行为准则并不具体设置。
例如可以将"人类"定义成一个抽象类,里面定义一个成员变量用来表示人的年龄。我们知道不同的人年龄可能是不一样的。"人类"这个抽象类只规定了年龄这一成员属性,但是创建对象时候的年龄,可以根据需要自行设置。这就是模板的作用。

接口的作用是为实现它的类制定相应的数据规范要求,不单单规定它应该有哪些成员变量和方法,还对成员变量的取值进行严格的要求,并且不允许更改(即定义成常量)。即接口是用来定义规范的。
例如我们用的手机壳,不同的手机壳背后的图案都是各不相同的,但是手机壳的尺寸大小却是有着严格的要求的,根据不同的手机型号,对相应的手机壳指定了严格的尺寸要求。
对于Java语言来说,就是可以将不同型号的手机对手机壳的尺寸要求定义成接口,实现了该接口的手机壳都要遵循改接口规定的尺寸要求,这就是接口的作用

接下来看接口在Java语言中的具体实现

先看接口的定义语法
[修饰符] interface 接口名
{
//零个到多个常量定义
//零个到多个抽象方法定义
//零个到多个内部类、内部接口、内部枚举类定义
//零个到多个默认方法或类方法定义
}
对于定义接口时的修饰符,只能是public和不写(即默认为default访问权限)。
接口名的规则和定义类名时候的规则一样,只是推荐使用英文中的形容词。

接口在定义的时候,是可以继承多个接口的,但是只能继承接口不能继承类。这一点和类之间的继承有很大的差别,类只能继承类,且类只能继承一个类。
总结:
接口只能继承接口,类只能继承类。那么问题:类在定义的时候如何使用接口?
类在定义的时候可以通过implement关键字类实现多个接口,类只能继承类,但是却可以实现多个接口。例如有三个接口分别为A、B、C
class AAA implement A, B, C
{

}

注意,类继承类和实现接口是可以同时进行的,但是要求先继承再实现。
classs AAA extends BBB implement A, B, C
{

}

再逐个分析接口中的内容:

1、零到多个常量定义。
对于这一点,要求定义的成员变量只能使用public修饰符修饰的static常量。即语法要求必须且只能使用public、static、final关键字来修饰成员变量。
public static final 类型名 变量名 = 初始值。
但是,由于只能写成public static final 类型名 变量名 = 初始值。这种形式,所以Java语法允许在定义接口成员变量的时候可以简写成类型名 变量名 = 初始值的形式,但是注意了虽然public static final没有手写但是系统是会帮助我们自动添加的。

所以在接口中定义成员变量的时候是有两种写法的,两种写法效果相同。即:
public final static 数据类型 变量名 = 初始值;
数据类型 变量名 = 初始值;
且两种写法是等价的

此处注意,对于一个接口来说,其内部是没有构造器和初始化块的(包括静态初始化块和普通初始化块),所以对于接口中的静态常量来说只能在定义的时候就立即初始化。

2、零到多个抽象方法的定义。
对于接口来说,其内部定义的抽象方法必须是有public修饰符修饰的抽象方法。所以接口中定义抽象方法的语法为:
public abstract 方法返回值类型 方法名(形参列表);
由于在接口中定义抽象方法的时候,由于只能且必须使用public修饰符进行修饰,同时在早期的时候,接口中定义的方法只能是抽象方法,即Java以前的接口中是没有默认成员方法和类方法的,只有抽象方法。
所以Java语法规定,当在定义抽象方法的时候,不写pubilc、abstract关键字的时候系统会默认添加上public、abstract关键字。即在定义抽象方法的时候有两种写法:
public abstract 方法返回值类型 方法名(形参列表);
方法返回值类型 方法名(形参列表);
注意两种写法是等价的。

注意,对于一个抽象类来说,里面定义的抽象方法所用的访问权限控制符除了private之外都是可以的(public、默认、protected都可以),但是在接口中定义抽象方法的时候对于访问权限控制符的使用将更加严格,只能使用public访问权限修饰符

3、零个到多个默认方法或类方法。(这是Java 8新增的功能)
个人感觉,接口中的默认方法其实就是相当在接口中定义了一个普通成员方法,只是对于类来说普通成员方法是不需要用default修饰的,但是接口中的普通成员方法是需要用default关机键字来修饰,而default关键字的英文含义就是默认的意思,所以接口中定义的普通成员方法由于用default关键字来修饰所有就被翻译成了默认方法。
所以,个人感觉接口中定义的默认方法其实就是相当于接口中定义的普通成员方法,只是该成员方法需要用default关键字来进行修饰。

在Java 8以前,接口中对于成员方法的要求是只允许定义public修饰符修饰的抽象方法,为了扩展接口的功能,Java 8 对其进行了扩展。即允许在接口中定义普通成员方法和类方法。
默认方法也就是带有方法体的普通成员方法,只是需要用default关键字来修饰。

Java 8规定在接口中定义默认方法的时候,该方法必须用default关键字修饰,同时访问权限控制符只能且必须使用public。
定义默认方法的语法规则:
public default 方法返回值类型 方法名(形参列表){方法体}//在语法上只是比在类中定义的普通成员方法多了一个default关键字。
由于对于类中定义的普通成员方法必须且只能用public关键字进行修饰,所以当我们不写public关键字的时候系统是会为其默认添加public关键字的。所以接口中定义默认方法有两种形式:
public default 方法返回值类型 方法名(形参列表){方法体}
default 方法返回值类型 方法名(形参列表){方法体}
两种写法等价。

为什么在接口中定义默认方法(普通成员方法)需要用default来修饰呢?
个人感觉,由于Java 8以前语法规定,接口中的成员方法只能是public修饰的抽象方法,所以对于接口中出现方法位置,如果没有写public abstract关键字那么系统就会为其自动加上public abstract关键字。
注意了如果此时你在接口中定义了一个带有方法体的方法,系统也是会为其添加public abstract关键字的,由于抽象方法不能有方法体所以此时会产生语法错误。

所以,当接口中添加了允许定义方法体的默认方法的时候,如果没有default关键字就无法在接口中区分哪些是需要帮助添加public abstarct关键字,哪些是不需要添加的。

例如在接口中定义了void method(){}这一方法,由于没有default关键字,系统是会给添加public abstract关键字的,即等价于public abstract void method(){}。但是,抽象类是不允许有方法体的,所以会产生于法错误,但是如果写成default void method(){}则系统就知道这是用户定义的默认方法,所以就不会再添加public abstract关键字了。

所以规定接口中定义默认方法(普通成员方法)的时候,必须有default关键字进行修饰。

Java 8也允许在接口中定义类方法,但是也必须且只能用public关键字进行修饰。即接口中定义类方法的语法规则为:
public static 方法返回值类型 方法名(形参列表){方法体],但是由于必须且只能用public关键字修饰,所以,当不写public关键字的时候系统也会为我们自动添加上public关键字的。
所以定义在接口中定义类方法也有两种写法
public static 方法返回值类型 方法名(形参列表){方法体}
static 方法返回值类型 方法名(形参列表){方法体}
两种写法等价。

4、零到多个内部类、内部接口、内部枚举类定义
关于什么是内部类、内部接口、内部枚举类有专门的章节进行讲解,在这里只需要记住一点,即它们也只能使用public关键字进行修饰,所以public关键字也可以省略不写,不写的时候系统会默认添加的。

问题1:为什么接口中的定义的成员变量必须使用public static final关键字来修饰?
个人感觉,由于接口的目的就是希望制定一种规范,能够使实现改接口的类遵循该接口制定的行为准则。所以,接口中的访问权限控制符无论是接口中的那种成员都必须是public关键字来修饰,以方便被类来实现。

由于接口的目的是希望被多个类来实现,反过来就是实现了同一接口的来类将遵循同一准则,这些准则是实现接口的类都需要遵守的,所以这些数据不是某一个类所有而是所有实现该接口的类共同所有,也就是该接口所有,所以定义成static。

由于接口是通过成员变量来指定相关的数据规范的,是多个实现该接口的类都需要遵守的,所以是不希望别改变的,所以需要定义成final变量。

同时该成员是被定义成了静态成员且是public关键字来修饰,所以任何一个实现该接口的类都是通过类名.成员变量名的形式访问到该成员变量。为了避免接口中定义的静态成员变量遭到某一个实现类的修改所以要定义成final修饰的变量。

问题2:为什么Java 8 以前的接口中方法的定义只允许定义抽象方法?
由于接口是用来指定多个类需要共同遵守的规范,所以在遵守数据规范的前提下,只需规定应该有哪些的行为准则具体即可,有关具体的实现可以在实现类中进行重写即可。

问题3:Java 8 为什么为接口增加了定义默认方法和类方法这一功能呢?
个人理解
因为不断地实践总结,在接口定义默认方法和类方法是很有必要的。
而且由于接口的目的就是制定规范标准,以前只是对数据进行了规范,方法仅仅是规定了实现类应该有哪些方法对具体实现没有进行要求。有了默认方法和类方法之后也能对接口的实现类进行方法上的约束了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值