接口(可多接口)
接口代表某个确切的功能,即只包含方法的定义,甚至都不是一个类。
接口包含了一系列方法的定义,类可以实现这个接口,表示类支持接口代表的功能
定义
接口用 interface 定义:
public interface Study{
void study(); //实际上是public abstract void study();但是由于接口中只能定义访问权限
// 为public的抽象方法,因此可以省略
}
此时,想要实现该接口的类就要在定义中重写study抽象方法了,当然也可以在定义中写上接口的默认实现(default)(Java8之后),这样在子类中可以选择不重写方法
接口中不能包含成员变量和成员方法,但可以存在静态变量和静态方法
在定义接口中的静态变量时,不必显示地给出,其默认类型为 public static final 型,这意味着该变量不能再次被赋值
默认方法(Java8)
定义格式:
public default 返回值类型 方法名(参数列表){}
注意事项:
- 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写时去掉default关键字
- public可以省略,default不能省略
- 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
例如:
public interface Study{
void study();
default void test(){
System.out.println("默认实现");//**注:默认实现不能是Object中已有的方法,但是可以重写**
}
}
静态方法(Java8)
定义格式:
public static 返回值类型 方法名(参数列表){}
注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
public可以省略,static不能省略- 如果接口中的静态方法与类中的静态方法名相同,由于静态方法不在虚方法表中,因此两个方法不是重写关系,想要调用只要
类名 / 接口名 + 方法名()即可
私有方法(Java9)
Java9后,允许接口中定义其private方法供内部使用:
public interface Study{
default void study(){
sout("默认实现");
inner();
}
private void inner(){
sout("一系列内部实现");
}
}
包括静态方法在内,也可以使用private访问权限进行声明
在外面使用接口对应的对象时,跟类一样无法访问到私有成员。
成员的特点
成员变量
只能是常量(默认修饰符:public static final)
构造方法
没有
成员方法
只能是抽象方法(默认修饰符:public abstract)
- Java7 以前:接口中只能定义抽象方法
- Java8:接口中可以定义有方法体的方法
- Java9:接口中可以定义私有方法
实现
类可以通过 implements 关键字来实现所需接口:
public class Student extends Person implements Study{
@Override
public void study(){
System.out.println("我会学习!");
}
}
注:在重写中使用接口的默认实现: 接口名.super.函数名()
如,在Student.java中:
public class Student extends Person implements Study{
public Student(String name,int age,String sex){ super(name,age,sex); }
@Override
public void study(){
Study.super.test();
System.out.println("我会学习!");
}
}
多个接口
public class Student extends Person implements Study,Walk,Eat{//多个接口用逗号隔开
}
使用
在Main方法中,可以直接通过接口名来定义一个变量:
Study student=new Student("小明",18,"男");
//此时student实质上还是Student类的引用,可以通过强制类型转换为Student类型
此时定义的变量只能使用接口中定义的方法:
student.study();
使用clone方法(clone为浅拷贝)
clone是Object类中的方法,但子类要使用该方法时必须要提供 Cloneable 的接口,即:
public class Student extends Person implements Clonable{}
此时,子类中重写的Cloneable方法,只需要把它的访问权限从protected改为public(否则外面不能用):
public class Student extends Person implements Cloneable{
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
Main中实现:
public class Main{
public static void main(String[] args) throws CloneNotSupportException{
Student stu=new Student("小明",18,"男");
Student clone = (Student) stu.clone(); //强制类型转换
}
}
即使clone为stu的克隆,在执行stu==clone时返回的也是false(因为是不同对象)
继承
接口也存在继承,同样使用 extends 关键字
需要注意的是,接口可以 多继承 ,即extends后面可以跟多个接口,其效果就是子接口包括父接口的所有方法
并且,当子接口和父接口存在同名方法时,子接口方法会覆盖父接口方法
特殊情况
当父类中存在子类所接接口中的同名方法时,且该接口存在默认实现,那么类的对象在调用该方法时执行的是父类中的方法
多态
当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态