一. 概念
- 定义:
接口是抽象类的更进一步, 抽象类中还可以包含非抽象方法, 和字段,而接口中包含的方法都是抽象方法, 字段只能包含静态常量。
public interface IShape {
int a=10;
void draw();
}
- 接口中的关键字 interface,使用 interface 定义一个接口
- 接口当中的方法,全部不能有具体的实现
- 接口中都是抽象方法,都是默认的—public abstract(一般不写)
- 接口当中的成员变量默认是public static final的,需要初始化
- 接口不可以单独被实例化,不能new, 接口存在的最大意义是被继承
- 类和接口之间的关系叫实现,实现的关键字:implements
class Rect implements IShape{
@Override
public void draw() {
System.out.println("画矩阵");
}
}
class Cycle implements IShape{
@Override
public void draw() {
System.out.println("画圈圈");
}
- 普通类若实现了接口,那么接口中的所有的方法都必须重写,抽象类可以不用重写
- 只要类和接口之间存在实现关系,就可以发生向上转型
- 接口是为了打破 java 中的单继承,接口可以实现多继承
// 定义两个接口
interface Ia{
void func();
}
public interface IShape {
int a=10;
void draw();
}
// 实现多继承
class Rect implements IShape,Ia{
@Override
public void func() {
}
@Override
public void draw() {
System.out.println("画矩阵");
}
}
- 一个普通类可以继承一个普通类,同时可以实现多个接口(继承在先,实现在后)
//定义两个接口
interface IRunning{
void run();
}
interface IJumpping{
void jump();
}
//定义一个父类
class Animal{
protected String name;
public Animal(String name){
this.name=name;
}
}
// 定义一个子类继承父类,且实现两个接口
class Cat extends Animal implements IRunning,IJumpping{
public Cat(String name){
super(name);
}
@Override
public void jump() {
System.out.println("jump");
}
@Override
public void run() {
System.out.println("run");
}
}
- 接口的优点:有了接口之后, 类的使用者就不必关注具体类型, 而只关注某个类是否具备某种能力
- 接口的拓展能力很强,接口与接口之间的关系是继承,不可以互相实现。例:Interface C extends A,B (此时C就包含了A,B的功能)
二. 接口的实例应用
- 自定义类型比较,需要实现接口 Comparable接口,并且重写CompareTo方法,(equals 比较是内容是否相等,CompareTo 比较的是字符串的大小)
//自定义类型进行排序,要在类里实现一个Comparable接口,并且重写CompareTo方法
class Student implements Comparable<Student>{
public String name;
public int age;
public double score;
public Student(String name,int age,double score){
this.name=name;
this.age=age;
this.score=score;
}
@Override
public String toString() {
return "Student{"+
"name='"+name+'\''+
",age="+age+",score="+score+
'}';
}
@Override
public int compareTo(Student o) {
return this.age-o.age; // 对象之间两两比较
// 姓名,年龄,分数都可进行比较
}
}
public class Test {
public static void main(String[] args) {
Student[] students=new Student[3];
students[0]=new Student("易烊千玺",19,100.0);
students[1]=new Student("苏静静",21,90.7);
students[2]=new Student("张零",20,85.3);
System.out.println(Arrays.toString(students));
Arrays.sort(students); //打印数组不需要System.out.println
System.out.println(Arrays.toString(students));
}
}
为了进一步加深对接口的理解, 可以尝试自己实现一个 sort 方法来完成刚才的排序过程(使用冒泡排序)
public static void sort(Comparable[] array) {
for (int bound = 0; bound < array.length; bound++) {
for (int cur = array.length - 1; cur > bound; cur--) {
if (array[cur - 1].compareTo(array[cur]) > 0) {
// 说明顺序不符合要求, 交换两个变量的位置
Comparable tmp = array[cur - 1];
array[cur - 1] = array[cur];
array[cur] = tmp;
}
}
}
}
2.克隆接口:Cloneable 接口,当中没有抽象方法,是空接口(标记接口)–》标志当前类可以被克隆,克隆后要重写克隆方法(抛出异常)
// class也要实现Cloneable 接口,否则无法拷贝
class Score implements Cloneable{
double s=89.6;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// 给自定义类型实现克隆的时候,要实现Cloneable 接口,并且重写clone方法
class Person implements Cloneable{
public String name;
Score score; // 组合
public Person(){
}
public Person(String name){
this.name=name;
this.score=new Score();
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person person=(Person)super.clone(); // 先克隆person
person.score=(Score) this.score.clone(); // 克隆当前对象person的score
// 最终达到深拷贝
//return super.clone(); //仅仅克隆了person
return person;
}
}
public class Test{
public static void main(String[] args)throws CloneNotSupportedException {
Person person1=new Person("嘿嘿");
Person person2=(Person) person1.clone();
person2.score.s=95.2;
System.out.println(person1.score.s);
System.out.println(person2.score.s);
}
}