java第九章学习笔记:接口---灵活性的基石

本文详细介绍了Java接口的使用,包括接口的声明、成员变量、方法的使用,以及接口与抽象类的区别。强调接口作为契约,定义了类可以具备的功能,而不提供具体实现。接口的成员变量默认为`public static final`,接口中的方法默认为`public abstract`。接口可多继承,提供基于接口的多态性,增强了代码的灵活性。接口与回调的概念也被提及,展示了如何通过接口处理事件监听。文章最后强调接口在实现多态和程序灵活性中的重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java的接口主要用来描述类可以充当什么样的角色,即描述类可以具有什么样的功能,但不给出每个功能的具体实现,本章包括:概述及特性、方法及成员变量在接口中的使用、接口与抽象类、基于接口的多态、接口与回调等
9.1 概述及其特性
定义一个接口,实际上是在编写一个契约,用来描述实现其的类能够做什么,能够充当什么样的角色,而接口中并没有功能的具体实现。
eg,编写一个飞行器接口Flyer,在该接口中定义起飞方法,这样具有飞行器功能(充当飞行器角色)的所有类都可以实现该接口,并具体实现接口中的方法,不同的类可以有不同的方法实现,接口声明语法如下:
*<访问限制修饰符>[abstract]interface<接口名>
{
//方法与成员变量的声明
}*

  • 其中访问限制修饰符与类的访问限制修饰符相同,可以是public或不写,含义也完全相同。
  • 若接口定义为public的,其必须位于与其同名的java文件中
  • 方括号中的abstract代表可选的,可写可不写,但如果不写,系统在编译时也会自动加上。也就是说接口一定是抽象的
  • interface关键字说明定义的是接口,与class说明定义的,是类一样。
    一对花括号中包含的称为接口体,其中可以声明接口中的方法与成员变量。
    提示:接口隐含了abstract,所以永远不能用final来修饰接口因为abstract代表抽象,而final代表最终(很具体)相互矛盾,
    下面给出两个合法的接口声明:
public abstract interface Flyer
{

}
public interface Sailer
{

}

组成接口名的各单词首字母大写,与类相同
接口也可以像类一样进行继承扩展,eg:喷气飞行器接口可以继承飞行器接口eg:

interface Flyer{}
interface JetFlyer extends Flyer{}

这样JetFlyer接口就具有了Flyer的所有功能,并且其可以定义自身特有的成员变量与方法,在java中类不允许继承多个类,但接口可以从任意多个接口继承eg:

interface Flyer{}
interface Jet{}
interface JetFlyer extends Flyer,Jet{}

JetFlyer接口同时继承了Flyer,Jet,两个接口之间用逗号分隔
接口只能继承自接口,接口以外的任何类型,都不能被接口继承。
提示:C++中没有接口,只有虚类,并且C++支持多重继承,实际上C++中的虚类是扮演了java中的抽象类与接口两个角色。
9.2 成员变量在接口中的使用
9.1 语法规则
与类不同的是,接口中只能定义常量属性,并且可以不必显示使用public、static和final进行修饰,即使不用这些修饰符,编译也会为其自动加上,即接口的变量隐含了“public static final “的eg:

interface IFEx
{
    int intConst1=12;//定义成员变量intConst1,并为其分配初值12
    public static final int intConst2=66;
}
public class Sample 
{
    public static void main(String[] args)
    {
        IFEx.intConst1=IFEx.intConst1+1;//Error:The final field IFEx.intConst1 cannot be assigned
    }
}

无法为最终变量intConst1指定值 ,将上述IFEx.intConst1=IFEx.intConst1+1代码修改为System.out.println("接口IFEx中的intConst1成员的值为:"+IFEx.intConst1);运行结果如下:
![这里写图片描述](//img-blog.youkuaiyun.com/20180317113040906?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTg4NTI4Mg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

回顾源代码,美誉创建人和对象,是用接口名调用的intConst1,这正好也说明了intConst1是static的。
提示:接口与类不同,其中不能有静态语句块等执行代码部分,而static final成员变量又必须赋值一次,而且赋值时间不能在类加载完毕以后,只能在声明的同时给出其值。
9.2.2 接口中成员变量的作用
接口相当于一份契约,契约具有的属性应该是不变的,因此接口内只能放置常量,这样做能保证实现该接口的任何类都可以访问相同的常量,不能动态将其值随意进行修改,同时使声明的常量也会增加代码的可读性
eg:若Flyer(飞行器)通过一些特定的int值来表示不同的飞行状态1表示高空飞行。2表示中等,3表示低空飞行,当使用时,这些数字难以记忆,但若用HIGH、LOW、MIDDLE这样的常量去代替数字,将使代码具有更好的可读性,当需要发生变化时,修改常量定义即可,不需要再程序中去导出修改数字。eg:

interface Flyer
{
    //HIGH、MIDDLE、LOW分别表示高空、中等、低空飞行
    public static final int HIGH=1;
    public static final int MIDDLe=2;
    public static final int LOW=3;
}

提示:在接口声明常量的时候,为了方便一般不写出修饰符“public static final”
这些常量可以被任何实现了该接口的类直接访问,就像在该类中定义了这些常量一样。eg:

interface Flyer
{
    //HIGH、MIDDLE、LOW分别表示高空、中等、低空飞行
    public static final int HIGH=1;
    public static final int MIDDLe=2;
    public static final int LOW=3;
}

class AirPlane implements Flyer
{
    public void setFlyHeight(int height)
    {
        switch(height)
        {
        case HIGH:
            System.out.println("我现在处在高空飞行状态");
            break;
        case MIDDLe:
            System.out.println("我现在处于中等高度飞行状态");
            break;
        case LOW:
            System.out.println("正处于低空飞行状态");
            break;
        }
    }
}
public class Sample 
{
    public static void main(String[] args)
    {
        AirPlane air=new AirPlane();
        air.setFlyHeight(Flyer.HIGH);
    }
}

这里写图片描述
类AirPlane实现了接口Flyer,因此接口中定义的内容也相当于在类中定义了,可以直接使用,eg:switch语句中的三个case
类Sample中没有实现接口,所以要使用接口中的成员必须使用接口名调用(Flyer.HIGH)当然也可以使用实现了接口的类的类名或引用来调用,主方法中Flyer.HIGH,也可以写为“AirPlane.HIGH”或air.HIGH
若以后要修改表示飞行状态的整数值,只要修改Flyer接口中的定义即可,不需要再修改使用这些常量的代码,因为常量是按名称使用的。

9.3 方法在接口中的使用

可以将接口看做“纯粹”的抽象类,因为接口中定义的方法必须是抽象的,原因是接口只是代表一个契约 ,表示实现其的类有什么样的功能。具体的实现由实现它的类完成
9.1 语法规则
定义接口中的方法时,需要满足以下规则:

  • 所有接口方法隐含都是public和abstract的,不需要在声明时加上;
  • 接口方法一定不能是static的,也不能是final的,也不能用public修饰符之外的其他访问限制修饰符进行修饰,也就是说,**要给接口中的方法写修饰符只能写public和abstract。**eg:一个合法的接口及其方法的声明
interface Flyer
{
    void fly();
}

所有接口方法都隐含是public和abstract的,就算不对其显示的进行修饰,编译器也会自动加上,所以上面的代码完全相当于下面的代码;

interface Flyer
{
    public abstract void fly();
}

9.3.2 如何实现接口

  • 接口实现的基本语法
  • 接口中的方法的方法的实现与使用
    1、接口实现的基本语法:
    使用关键字implements可以使某个类实现指定的接口,其基本语法如下:
    class <类名> implements <接口名列表>
    接口名列表可以有多个接口名,因为接口代表的是角色,一个类可以扮演多个角色eg:合法的接口实现的代码片段:
interface Developer
{

}
interface Lecture
{

}
class Person implements Developer,Lecture
{

}

Person是一个类,代表自然人,其实现了Developer,Lecture接口,表示同时扮演开发人员与演讲者两个角色
2、 接口中的方法的方法的实现与使用
类的继承可以使得开发人员可以处理同类的事务,但不能处理不同类但具有相同功能的事务。接口能够被很多不同的类实现,其相当于一个契约或角色,实现接口的不同类之间不需要任何继承关系,他们只是扮演接口的角色或说是签订了契约,这可以让开发者从角色的角度来处理多个类的关系。
eg:飞机与鸟都可以充当飞行器(Flyer)这个角色,但二者之间没有任何继承关系,但飞机与鸟通过实现Flyer接口后,使其都能够作为飞行器进行处理,因为类对接口的实现有上述含义,因此当一个类实现了某个接口,其应当为该接口中的所有方法提供具体实现,除非该类为抽象类,demo:

interface Flyer
{
    public void fly();
}
interface Sailer//水上航行器
{
    public void dock();
}
abstract class AirPlane implements Flyer
{
    public abstract void doAirPlaneThing();
}
class SeaPlane extends AirPlane implements Sailer
{
    public void fly()
    {
        System.out.println("水上飞机可以飞行");
    }

    @Override
    public void dock() {
        System.out.println("水上飞机可以航行。");

    }

    @Override
    public void doAirPlaneThing() {
        System.out.println("水上飞机是一个飞机");

    }
}

public class Sample 
{
    public static void main(String[] args)
    {
        SeaPlane sp=new SeaPlane();
        sp.fly();
        sp.dock();
        sp.doAirPlaneThing();
    }
}

这里写图片描述
从上例可以看出,水上飞机对象拥有了飞机的一切功能,eg:可以飞行,可以做飞机能做的事情,同时还可以扮演水上航行器的角色,可以在水上航行。
9.3.3 接口引用的使用
1. 可以指向的对象类型
2. 接口引用间的赋值
3. 类引用与接口引用间的赋值
1、可以指向的对象类型:
接口不是类,所以接口不能new关键字进行实例化,eg:下面的demo是非法的:

interface Fly{}
Fly f=new Fly();//不能实例化

但是可以使用接口类型的引用,当某个类实现了接口以后,这个类的对象可以用其实现的接口或父接口类型的引用来指向,也就是说,**接口引用可以指向间接或直接实现该接口的所有类的对象。**eg:

        Flyer f=new SeaPlane();
        Sailer s=new SeaPlane();

Flyer被水上飞机类间接实现了,故其对象可以用Flyer引用指向;
水上飞机类直接实现了Sailer接口,其对象可以用Sailer型引用指向;
提示:通过接口型引用来使用对象比用类引用具有更好的灵活性
2、 接口引用间的赋值引用:
接口引用间赋值需要一定的规则,与类引用赋值类似

  • 子接口引用可以直接赋给父接口引用
  • 父接口引用不能直接赋值给子接口引用,需要强制类型转换
  • 其他没有继承关系类型的接口引用也需要强制类型转换eg:
interface Developer
{
}
interface JavaDeveloper extends Developer
{

}
interface Lecture
{

}
class Person implements JavaDeveloper
{

}
public class Sample 
{
    public static void main(String[] args)
    {
        JavaDeveloper jd=new Person();
        Developer d=jd;
    }
}

JavaDeveloper类型的引用指向Person对象是可以的因为Person类实现了JavaDeveloper接口。
将JavaDeveloper类型的引用赋值给Developer类型引用d也是可以的JavaDeveloper接口是Developer的子接口
在main方法中再加上如下代码:
这里写图片描述
将上面的代码修改为:再次编译

jd=(JavaDeveloper)d;
Lecture l=(Lecture)d;

则顺利通过
与引用类型不同,任意两个接口的引用都可以进行强制类型转换,不一定需要强制类型转换后的接口与转换前的接口类型有继承关系。
因为java中的引用是用来指向对象的,一个对象中所在的类可以实现很多个没有关系的接口,java中的引用是用来指向对象的,一个对象所在的类可以实现很多个没有关系的接口,但这些类型的接口都是可以指向其对象,但是要事实上指向的对象不满足要求则会运行时异常eg:

interface Developer
{
}
interface JavaDeveloper extends Developer
{

}
interface Lecture
{

}
class Person implements JavaDeveloper
{

}
public class Sample 
{
    public static void main(String[] args)
    {
        JavaDeveloper jd=new Person();
        Developer d=jd;
        jd=(JavaDeveloper)d;//Error:不能直接将父接口赋值给子接口
        Lecture l=(Lecture)d;//两个没有关系的接口不能直接赋值需要强制类型转换
    }
}

这里写图片描述

3、 类引用与接口引用间的赋值
类引用与接口引用间赋值规则:
- 类引用赋值给接口引用不需要进行强制类型转换,编译时检查类是否直接或间接的实现了接口,若编译通过可以运行。
- 接口引用给类引用需要强制类型转换,但不是随便转换就可以,必须目标类实现了接口才能编译,若运行时类对象不符合则报异常。eg:

interface IFEx1
{}
interface IFEx2{}
class CEx implements IFEx1{}


public class Sample 
{
    public static void main(String[] args)
    {
        CEx ce=new CEx();
        IFEx1 ife1=ce;//类引用可以直接给接口引用(小的可以直接给大的)
        ce=(CEx)ife1;//Error:c cannot be resolved to a variable(接口引用给类引用需要强制类型转换)
        IFEx2 ife2=ce;//Error:cannot convert from CEx to IFEx2(CEx类没有实现IFEx2的接口)
        String s=(String)ifex1;//Error:String类没有实现IFEx1接口
    }
}

这里写图片描述
9.3.4 接口中方法无法使用的修饰符(只能用public和abstract)
因为接口中的方法是抽象的,而且接口是对外公开的。所以就不能将其修饰为静态的、最终的或者是非public的访问限制。
1、接口方法与static
- 如果接口中的方法是static的,那就意味着不能被重写,但是接口中的方法都是抽象的是必须被重写的。否则该方法将没任何意义,eg:

interface Flyer{
    public static void fly();//Error:Illegal modifier for the interface method fly; only public & abstract are permitted
}

2、接口中的方法与final
final两个相冲突,一个组织重写一个可以重写,接口中的方法是抽象的,所以永远不能是最终的。

interface Flyer{
    public final void fly();//Error:Illegal modifier for the interface method fly; only public & abstract are permitted
}

3、接口中的方法访问限制修饰符
接口中的方法的访问限制已经被默认为public类型的,所以不能再用别的访问限制符对其修饰eg:

interface Flyer{
    private void fly();//Error:Illegal modifier for the interface method fly; only public & abstract are permitted
    protected void land();//Error:Illegal modifier for the interface method land; only public & abstract are permitted
}

若接口中的方法为非public的,则就不能保证其能够被任何类所实现。

9.4 接口与抽象类

接口与抽象类在语法上有明显的区别,下表列出了他们语法上的不同之处。
这里写图片描述
接口与抽象类在语法上有很大的不同之处,接口要比抽象咧更灵活、选择性更大的特点。
9.4.2 具体含义的不同
抽象类更注重其是什么?更注重本质,而接口则不是,接口更注重其具有什么样的功能。
eg :可以充当飞行器的事物有很多,比如飞机,鸟或者超人,但是飞机的实质是个机械工具,需要汽油;而鸟与超人的实质是动物,需要进食,所以,鸟可以继承自动物,但其扮演飞行器这个角色,当然继承自飞机的水上飞机,还具有水上航行器的角色。eg:

public class Test
{
    public static void main(String[] args)
    {
        SeaPlane seaPlane=new SeaPlane();
        Brid brid=new Brid();
        System.out.println("============水上飞机执行的动作==============");
        seaPlane.cruise();
        seaPlane.consume();
        seaPlane.fly();
        System.out.println("============鸟执行的动作==============");
        brid.fly();
        brid.eat();
    }
}

interface Flyer{
    public void fly();
}
interface Sailer
{
    public void cruise();
}
abstract class Vehicles
{
    public abstract void consume();
}
abstract class Animal
{
    public abstract void eat();
}
abstract class AirPlane extends Vehicle implements Flyer
{
    public void consume()
    {
        System.out.println("我需要消耗汽油。。");
    }
    public void fly()
    {
        System.out.println("我可以用飞机的方式在天上飞、。。");
    }
}
class SeaPlane extends AirPlane implements Sailer
{
    public void cruise()
    {
        System.out.println("我可以用船的方式在水上航行。。");
    }
}
class Brid extends Animal implements Flyer
{
    public void eat()
    {
        System.out.println("我需要吃东西。。");
    }
    public void fly()
    {
        System.out.println("我可以用动物的方式在天上飞");
    }
}

这里写图片描述
从上例中可以看出,水上飞机与鸟有相同之处,即都会飞,也就是都实现了飞行器这个接口,但是水上飞行棋与鸟之间有本质的区别,即其没有任何继承关系,一个是机械一个是动物,同时,水上飞机还可以充当水上航行器的角色。
接口的实现与抽象类的继承其含义是不同的,应站在不同的角度看待这两个概念,抽象类是看待物体的本质,接口是看待物体可以充当的角色。

9.5 基于接口的多态

上一章介绍基于继承的多态时,提到了基于接口的多态要比基于继承的多态灵活性更好。
eg:苹果和牛肉都可以充当食物角色,而苹果属于水果,牛肉属于肉类,水果引用不可能指向牛肉对象,同样肉类引用也不可能指向苹果对象,但是食物引用则可以指向这两个毫不相干的类的对象,有了更大的灵活性,这通过继承是无法实现的,类与接口的 引用指向对象时的区别:

  • 继承只能让超类引用指向与其属于同一类的对象,eg:肉类引用只能指向属于肉的对象。
  • 接口引用则能指向任意类型的对象,即使对象间没有任何关系,只要这些对象所在的类实现了该接口即可。eg:
public class Test
{
    public static void main(String[] args)
    {
        Food food=new Apple();
        food.doEat();
        food=new Beef();
        food.doEat();
    }
}
interface Food
{
    public void doEat();
}
abstract class Fruit{}
abstract class Meat{}
class Apple extends Fruit implements Food
{
    public void doEat()
    {
        System.out.println("我是苹果,我属于水果,我可以充当食物角色被吃掉。。");
    }
}
class Beef extends Meat implements Food
{
    public void doEat()
    {
        System.out.println("我是牛肉,属于肉类,我可以充当食物角色被吃掉。。");
    }

}

在主方法中用食物接口引用food指向了创建的苹果对象,并且调用其食用的方法,接着用同样的引用指向创建的牛肉对象,并且以同样的方式调用了其食用的方法。
运行结果:
这里写图片描述
可看到本例使用接口引用指向了两个毫不相干的对象,只是这两个对象都实现了该接口,而对调用方来说其调用的都是同样的方法,但是实际上运行了接口的不同实现,打印出不同结果,而不需要考虑调用对象之间是否有本质的联系,这就是基于接口的多态。
基于接口的多态要比基于继承的多态更具有选择性,灵活性更大,也就是说基于接口的耦合比基于抽象类的耦合的选择性,灵活性大。

9.6 接口与回调

回调是常见的设计模式,利用回调技术可以处理这样的问题,事件A发生时要执行处理A代码,判断何时发生事件A及何时执行处理的代码是固定的,先行编写完毕,供很多人使用。但事件A的处理代码开放给其他开发人员编写,可以有很多不同的实现,使用时可以注册需要的实现来处理。
java中的Swing与AWT的事件监听处理模型就是使用接口与回调实现的,学习那部分内容后可以进一步深入体会接口与回调带来的好处,举例如下:

public class Test
{
    public static void main(String[] args)
    {
        MyMoniter mm=new MyMoniter();
        ProcessorA pa=new ProcessorA();
        ProcessorB pb=new ProcessorB();
        mm.regListener(pa);//注册A处理器
        mm.generalProcessEvent();//发送事件处理请求
        mm.regListener(pb);
        mm.generalProcessEvent();
    }
}
interface MyListener
{
    void specialProcessEvent();
}
class MyMoniter
{
    MyListener ml;
    public void regListener(MyListener ml)//注册监听方法
    {
        this.ml=ml;
    }
    public void generalProcessEvent()//事件处理方法
    {
        this.ml.specialProcessEvent();//接口方法

    }
}
class ProcessorA implements MyListener 
{
    public void specialProcessEvent()
    {
        System.out.println("我采用A策略处理事件");
    }
}
class ProcessorB implements MyListener
{
    public void specialProcessEvent()
    {
        System.out.println("我采用B策略处理事件。。");
    }
}

MyListener为事件处理接口,其中有specialProcessEvent方法表示处理事件方法;
MyMoniter类是一个监听器,当有事件发生时,通知监控类(调用其generalProcessEvent方法)处理事件,而generalProcessEvent方法调用注册到监控器的处理器中specialProcessEvent方法来对具体事件处理。
MyMoniter中的regListener方法允许把不同的处理器注册给监控者。
ProcesserA和ProcesserB是实现了事件处理接口的两具体的处理器,分别对事件采用不同的处理方法,运行结果为:
这里写图片描述
由于两次事件处理前注册了不同的处理器实现,故两次事件处理执行的具体任务不同,若需要可自己实现更多不同的处理器,这就提供了很高的灵活性。

9.7 instanceof的使用

在实际运行时,由于多态的原因,引用指向的对象不一定是引用类型的,这时需要测试引用指向的对象的类型情况,就会用到instanceof关键字
9.7.1 基本语法及使用
功能:检查引用指向的对象是否可以看做指定的类型,基本语法如下:
<引用>instanceof<类或接口类型>
表达式返回boolean值,当引用指向的对象可以看做是指定的类或接口类型时返回true,否则返回false
下面将从三个方面说明instanceof的使用方法:

  1. 基本的使用
  2. null引用的使用
  3. 数组引用的使用
    1、基本的使用:
    eg:
public class Test
{
    public static void main(String[] args)
    {
        Son s=new Son();
        if(s instanceof Son)
        {
            System.out.println("s指向的对象可以看做Son类型。。。");//yes
        }
        if(s instanceof Father)
        {
            System.out.println("s指向的对象可以看做Father类型。。。");//yes
        }
        if(s instanceof ISon)
        {
            System.out.println("s指向的对象可以看做ISon类型。。。");//yes
        }
        if(s instanceof IFather)
        {
            System.out.println("s指向的对象可以看做IFather类型。。。");//间接继承IFther
        }
    }
}
interface IFather{}
interface ISon extends IFather{}
class Father{}
class Son extends Father implements ISon
{

}

这里写图片描述
从本例中可以看出,instanceof不能用来测试对象到底是哪个特定的类型,因为对象所在的类型及其父类都能测试通过,要判断对象是不是某个具体类型,请参照反射章节。
2、 null引用的使用:
若测试的引用为null,其结果永远返回false,eg:

public class Test
{
    public static void main(String[] args)
    {
        String s=null;
        if(s instanceof String)
        {
            System.out.println("恭喜你,测试通过。。");
        }else
        {
            System.out.println("很遗憾,测试不通过");
        }
    }
}

运行结果:
这里写图片描述
3、数组引用的使用:
需要注意的是,数组也是对象,其引用也可以用instanceof进行测试eg:

public class Test
{
    public static void main(String[] args)
    {
        int[] intArray=new int[5];
        if(intArray instanceof int[])
        {
            System.out.println("intArray是int[]类型的");
        }
        Son[] sonArray=new Son[12];
        if(sonArray instanceof Son[])
        {
            System.out.println("sonArray是Son[]类型的");
        }
        if(sonArray instanceof Father[])
        {
            System.out.println("sonArray是Father[]类型的");
        }
    }
}

class Father{}
class Son extends Father 
{

}

运行结果:
这里写图片描述
对数组而言子类型数组可以看做父类型的数组。
提示:对于基本数据类型的数据,不可以看做其他任何类型的数组对象。
9.7.2 不允许进行测试的情况
是否任何类型的引用对任何类型的类或接口都可以测试呢?答案是否定的。因为大象类型的引用与苹果类进行测试是没有任何意义的。大象类型的引用指向的对象永远不可能看做苹果类型。
实际规则是:要想instanceof测试能通过编译,参与测试的引用类型必须能够强制类型转换为测试的类或接口类型,若强制类型转换通过,就可以进行instanceof测试,eg:

public class Test
{
    public static void main(String[] args)
    {
        Son s=null;
        if(s instanceof Father)
        {

        }
        if(s instanceof String){}//Error:不可转换的类型
        int[] intArray=null;
        if(intArray instanceof long[])
        {
        }
        Son[] sonArray=null;
        if(sonArray instanceof Father)
        {
        }
        if(sonArray instanceof String)//Error:Incompatible conditional operand types Son[] and String
        {

        }
    }
}

class Father{}
class Son extends Father 
{

}

这里写图片描述
“s instanceof String”报错,因为引用s所在的类与String没有相互派生的关系,故s不能强制类型转换为String
”intArray instanceof long[]“报错是因为基本类型的数组引用不可以转换成其他别的数组类型
“ sonArray instanceof Father[]”编译通过是因为引用类型的数组引用可以强制类型转换,但要求转换前后的数组元素有派生关系而Son继承了Father。
“sonArray instanceof String[]”报错是因为Son和String无继承关系
提示:在强制类型转化执前先执行instanceof测试,若通过测试再进行强制类型转换避免运行时抛出“java.lang.ClassCastException”异常

9.8小结

接口是java中实现多态与程序灵活性的一项重要手段。
第九章,完。。坚持一百天,加油
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值