【自学】Java核心技术卷1_6.1-6.2接口

接口的特性

  • 对类的一组需求描述,对方法制定的一套规范。
  • 接口没有实例对象(不能new实例对象),没有实例域(对象的值),
  • 可以定义接口变量,引用实现了接口的类的对象
  • 可用instanceof检查一个类是否实现了某接口:if(anObject isstanceof anInterface){…}
  • 类只能extends一个超类,但却可以implements多个接口(逗号隔开)
  • 接口可以extends多个接口(逗号隔开)
  • 域:public static final (自动)
  • 方法:public abstract (自动);default(为方法提供默认实现)
  • 从Java SE 8开始,允许在接口中增加静态static方法,并给静态方法提供方法体实现,该静态方法只能通过接口名.静态方法来调用。实现语法只要在方法前面加static关键字即可,这理论上讲是可以的,但这有违于接口作为抽象规范的初衷。静态方法只能被具体实现类继承,不能在实现类中重写。通常将static方法放在接口的伴随类中。
  • 类实现接口:implements声明,实现接口方法(显式声明public)

接口与抽象类的区别

接口interface

抽象类abstract class

interface Demo{

         void method1(); //自动public abstract

         void method2();

}

public abstract class Demo{

         abstract void method1();

         void mehtod2(){…}

}

implements

extends

public static final域

public abstract方法

default、static方法(Java 8新增)

域、方法、构造器

包含抽象方法的类一定是抽象类,

不包含抽象方法的类也可以声明为abstract

like a,子类实现接口方法后,具备相应功能

子类is a抽象类,是抽象类的特例化

子类可以implements多个接口

子类只能extends一个抽象类

接口可以extends多个接口

 

对行为的抽象,子类之间不必有联系

eg:鸟和飞机类都能“飞”,所以可以定义包含“飞”这个方法的接口,通过接口变量就可以调用不同类的飞行方式(多态)

对子类的抽象,子类的公共属性、行为

eg:老师和学生类都是人,可以定义抽象类人,包含人的共同属性“姓名”、共同方法“呼吸”,和要根据子类特殊化的抽象方法“工作”,通过抽象类变量调用不同子类的工作方式(多态)

共同点:

没有实例对象,

可以创建引用变量,引用子类对象

若子类没有实现所有抽象方法,则子类要声明为抽象类

接口的默认方法

  • 默认方法用default修饰
  • 默认方法与“接口演化”:为一个已经定义并使用很久的接口添加一个新的方法时,将这个方法定义为默认方法,就可以保证之前实现了这个接口的类仍能通过编译(重新编译后旧类中就有了接口中新添加的默认方法,即使这个旧类没有重新编译,通过jar文件加载,并用其实例调用到了新添加的默认方法,也会调用接口的默认方法,不会出错)
  • 默认方法可以调用其他任何方法

默认方法冲突

  • 情况1:超类优先。类扩展了超类且实现了接口,超类提供了一个具体方法,则接口同名同参的默认方法会被忽略。(但是如果接口的方法只是同名同参且不是默认方法,则会冲突报错
  • 情况2:类实现了两/多个接口,接口有同名同参方法,且至少有一个提供了默认实现,则类必须覆盖这个同名同参的方法来解决冲突(接口的共享方法都没有提供默认实现则不冲突)

重名常量的冲突

  • 1)超类和接口冲突。如果一个类继承了一个超类和实现了若干接口,此时不像默认方法冲突一样有超类优先原则。只能通过在实现类中覆盖该常量来解决冲突。
  • 2)多接口之间冲突。如果一个类实现了多个接口,而这些接口又有重名常量,此时会发生冲突。必须用接口名.常量的方式来精确指明要使用的常量。

默认方法和多继承

1、多继承

  • 若父接口有相同签名的默认方法,则子接口必须override,否则冲突报错 (方法签名:方法名,参数类型)
  • 若父接口的默认方法的签名不同,则子接口同时继承所有默认方法
//D->A,B,C
interface A {
    default void say(String name) {
        System.out.println("hello " + name);
	}
}
interface B {
    default void say(String name) {
        System.out.println("hi " + name);
	}
}
interface C{
    default void say(int name){
    }
}
interface D extends A,B,C{
    default void say(String name){   //若此处没有重写则AB的say方法会冲突
        System.out.println("greet"+name);
    }
    //D隐式继承了C的say方法,不与AB的say冲突
}

2、接口多层继承

//C->B->A
interface A {                    //第一层A
    default void say(int a) {
        System.out.println("A");
	}
    default void run() {
        System.out.println("A.run");
	}
}
interface B extends A{           //第二层B extends A
    default void say(int a) {    //override接口A的同签名方法say
        System.out.println("B");
	}
    default void play() {        //B新定义的play方法
        System.out.println("B.play");
	}
    //B隐式继承A的run方法
}
interface C extends B{            //第三层C extends B
    //say();  B重写后的say()
    //play(); B定义的play()
    //run();  A定义的run()
}

3、多层多继承(子类只看自己最近的父类、父接口)

//A2->A1
//C->A2,B
//D->A2,A1
interface A1 {
    default void say(int a) {
        System.out.println("A1");
		}
	}
interface A2 extends A1 {
		//隐式继承A1的say()
	}
interface B {
    default void say(int a) {
        System.out.println("B");
		}
	}
interface C extends A2,B{
    default void say(int a) { //overrideA2与B冲突的say()
        B.super.say(a);       //通过调用指定接口的默认方法消除二义性
		}
	}
interface D extends A2,A1{
    //D隐式继承A2的方法
}

4、类+接口继承

  • 若接口中有与超类同签名的默认方法,则子类优先继承超类的方法,忽略接口的同签名默认方法
  • 若接口中的方法与超类签名不同,则由子类实现
//C->B,A
interface A {
    default void say() {
        System.out.println("A");
	}
    default void run() {
    }
}
static class B {
    public void say() {
        System.out.println("B");
	}
}
static class C extends B implements A{
    //interface A的say()被忽略,优先继承超类B的同签名say()
    //隐式继承A的不同签名的run()
}
public static void main(String[] args) {
    C c = new C();
    c.say(); //B
}

标记接口:Cloneable

  • 标记接口不包含任何方法,唯一作用就是允许在类型查询中使用instanceof
  • Cloneable:A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.(类实现Cloneable接口表示此类的对象可用Object类的clone()方法克隆)
  • clone():Object类的protected方法。子类只能调用protected的clone()方法来克隆它自己的对象,必须重定义clone()方法为public才能允许所有方法克隆对象,即使Object类clone()的默认实现(浅拷贝)能够满足要求,还是需要实现Cloneable接口,将clone()重新定义为public,再调用super.clone(),还可以为新定义的clone()指定返回类型
  • 如果类没实现Cloneable接口,但其对象调用clone()方法,则会抛出异常CloneNotSupportedException,所以子类重新定义clone()方法时最好声明此异常
  • 所有数组类型都有public的clone()方法,用于建立一个包含原数组所有元素副本的新数组

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值