写在最前
先看看抽象类和抽象方法
-
使用abstract修饰的方法叫做抽象方法,包含抽象方法的类叫做抽象类!
-
如果一个类包含一个以上的抽象方法,那么这个类必须也用abstract进行声明。
-
抽象方法是不完整的,不包含方法体;
-
抽象类中是可以有完整的方法的,如果要new一个抽象类,那么必须重写其中的抽象方法:
-
如果一个类想继承一个抽象类,那么就必须重写这个类中的所有的抽象方法!和上面同理(否则这个类也必须使用abstract进行修饰!)
-
如果一个抽象类中没有抽象方法,那么这个类不能被直接new出来
接口究竟是什么?
-
一个接口表示的是:“所有实现了该接口的类,都需要按照接口的样子来实现类中的方法,因此接口就相当于是一个用来创建类的协议”
-
interface 关键字比抽象类更接近抽象的概念(毕竟抽象类中还是可以存在非抽象方法的)
-
interface 这个关键字产生一个完全抽象的类(但在JDK8和JDK9中对接口中可以写带有方法体的方法(default,private,static;这个最后再说))
-
能够通过接口来实现向上转型
-
接口可以用public声明(公共权限),也可以不写,默认使用的是包访问权限
-
接口中是允许存在域的,且域是隐形的static + final (全局唯一且不可改变),当然也是public的,理解起来很简单,因为接口更像是一种协议规范,约定实现类该怎么做,因此域只有一份且不能改变。
-
接口中可以将方法显式地声明为public,但是如果不写,他们也是public的,理解起来也很简单,因为是协议嘛,不然不同的包下是用不了接口。
-
【另外】一个类可以实现多个接口!
Java中的多重继承
- Java中的接口支持多重继承,我们可以通过继承来扩展接口,代码如下:
interface A{
public void a();
}
interface B{
public void b();
}
interface C extends A,B{
public void C();
}
class D implements C{
public void a() {
}
public void b() {
}
public void C() {
}
}
组合接口时的命名冲突?
- 如果在通过继承扩展接口的时候,两个结构中有定义相同的方法,怎么办?
- 如果方法签名完全相同(包括参数和返回类型)其实没有什么担心的,因为接口只是相当于一种规范实现类的协议,就相当于两份不同的协议有一条相同的约定,实现类满足其中任意一个即可
interface A{
public void a();
public void a(int name);
}
interface B{
public void a();
}
interface C extends A,B{
public void C();
}
class D implements C{
public void a() {
}
public void a(int name) {
}
public void C() {
}
}
- 如果方法签名不相同,那就会编译出错!这是多继承的一个坑!
- 因为多态之前讲过:并不能用返回值加以区分,会过不了编译。在下面这个例子中的C接口的a方法,如果用的时候,参数列表是相同的,返回值继承的一个是void,一个是String,使用C接口调用方法的时候,就不能通过多态进行区分,所以编译不通过!
接口中的域有何特点?
- 因为放入接口中的任何域都会自动变为public + static + final,因此接口就成为了一种很便捷的用来创建常量组的工具
- 在Java SE5之前,在接口中创建常量是实现C和C++的枚举类型的唯一方法。
- 在Java SE5之后,Java有了enum枚举类型,这个时候就不用使用接口来特意创建一些常量组了。
- 如果在review一些老代码的时候,所以看到接口中有类似枚举类型的常量,不要惊讶~
初始化接口中的域需要注意?
- 注意!Java类中是允许域存在空final现象的,因为前提是需要在每个构造器中均进行显式地初始化!
- 但是接口中不存在构造器的说法,因此,接口中不允许空final!每个域都必须在定义的位置初始化!隔开一行先定义后初始化都不行!
- 当然这些域并不是接口的一部分。。他们是static的,它们的值被存储在该接口所在的静态存储区域内。
嵌套接口?
- 接口可以嵌套在类或者别的接口内
- 在类中嵌套的接口,访问权限可以是public或者包访问权限,甚至可以是private!(内部嵌套类也是这样的,内部类可以用private权限修饰符进行修饰)
jdk8与jdk9中接口的新特性
-
1.8之后接口可以有方法体(有默认方法和静态方法)1. 8之前只有全局抽象方法和全局静态常量
-
需要声明一个默认的实现的方法default
-
如果在实现类中对say方法进行重写,那么以多态的方式向上转型,调用say方法,通过后期绑定的是实现类的重写后的方法(如下)
interface A {
default void say(String sth){
System.out.println(sth);
}
}
class Solution implements A{
@Override
public void say(String sth) {
System.out.println("override"+sth);
}
public static void main(String[] args) {
A a = new Solution();
a.say("wang");
}
}
输出
- 有关静态方法,也是可以声明的,static 带方法体
- 如上的目的是?目的是给函数式编程(一个接口只定义一个方法)留个后门
- JDK1.9可以定义private方法(带方法体)。这个private可以在default和static中进行调用