“全栈2019”Java第七十八章:内部类可以继承其他类吗?

难度

初级

学习时间

30分钟

适合人群

零基础

开发语言

Java

开发环境

  • JDK v11
  • IntelliJ IDEA v2018.3

提示

本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。

1.复习继承相关知识点

继承是我们的老朋友了,之前我们也学过继承。

这里简单复习一下:

继承只能发生在类与类,接口与接口之间。

类与类之间只能单继承,不能多继承。

接口与接口之间可以多继承。

类与类继承,存在字段的隐藏,实例方法的重写,类方法的隐藏等特性。

类与类之间不能存在循环继承,什么叫循环继承。就是A继承B,B继承C,C再继承A,这就叫循环继承。A继承A也是循环继承。

好了,简单复习了一下继承相关知识点,如果需要深入连接的同学,请点击下面链接:

“全栈2019”Java第四十四章:继承

“全栈2019”Java第四十六章:继承与字段

“全栈2019”Java第四十七章:继承与方法

2.内部类继承外部类

内部类目前我们学习了四种:内部类、静态内部类、抽象内部类、静态抽象内部类。

抽象内部类与内部类大致一样,只不过抽象内部类是抽象的。

静态抽象内部类与静态内部类大致一样,只不过静态抽象内部类是抽象的。

综上所述,我们就不全演示,这里拿内部类和静态内部类演示即可。

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner和一个静态内部类NestedInner。然后内部类和静态内部类继承外部类。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

内部类和静态内部类继承外部类没有任何问题。

继承成功之后,我们可以使用super关键字吗?来试试。

演示:

请在外部类Outer中定义一个实例变量和一个类变量。

请在内部类和静态内部类中使用super关键字。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

从运行结果来看,外部类中的实例变量是每创建一个新对象都会重置,而类变量则不会重置,所以值一直累加。

3.内部类继承内部类

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner和一个静态内部类NestedInner,还有一个内部类FuInner,然后内部类Inner和静态内部类NestedInner继承外部类FuInner。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

错误信息:

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Outer.java

Error:(20, 27) java: 内部类lab.Outer.FuInner中的静态声明非法

修饰符 'static' 仅允许在常量变量声明中使用

由于我们在内部类FuInner中定义了类变量导致的错误,内部类里面不能定义类变量,只能定义静态常量。所以我们先将类变量和与之相关的调用都去掉:

再运行:

错误信息:

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Outer.java

Error:(42, 30) java: 作用域中没有类型为lab.Outer的封闭实例

该错误原因是静态内部类只能继承外部类、静态内部类或者静态抽象内部类,不能继承内部类和抽象内部类。我们先将静态内部类去掉:

Outer类:

Main类:

再运行:

然后就可以了,我们发现内部类继承内部类的时候,需要注意的事项很多,比如内部类里面不能存在静态成员,除静态常量以外;静态内部类不能继承内部类,只能继承外部类或静态内部类或静态抽象内部类。

4.内部类继承静态内部类

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner和一个静态内部类NestedInner,还有一个静态内部类FuInner,然后内部类Inner和静态内部类NestedInner继承静态内部类FuInner。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

内部类和静态内部类继承自静态内部类,这是被允许的,而且父类中也可以定义静态成员,我们子类也可以使用this和super进行访问。

5.内部类继承抽象内部类

鉴于前面静态内部类继承内部类的错误,我们就直接避开错误直接演示可行性部分。错误原因第3小节也解释的很清楚了。

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner和一个静态内部类NestedInner,还有一个抽象内部类FuInner,然后内部类Inner和静态内部类NestedInner继承抽象内部类FuInner。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

从运行结果来看,内部类和静态内部类继承抽象内部类的可行性部分没有任何问题,不可行部分我已经将其注释起来,大家在写的时候不必书写上去,注意就好。

6.内部类继承静态抽象内部类

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner和一个静态内部类NestedInner,还有一个静态抽象内部类FuInner,然后内部类Inner和静态内部类NestedInner继承静态抽象内部类FuInner。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

从运行结果来看,内部类和静态内部类继承静态抽象内部类没有任何问题。静态抽象内部类里面可以定义静态成员,作为子类的内部类和静态内部类都可以访问到。

7.外部类继承内部类

请问外部类能不能继承内部类呢?

答案是可以的。

演示:

请定义一个外部类Outer,在外部类Outer里面定义一个内部类Inner,然后外部类Outer继承内部类Inner。在Main类的main()方法中创建外部类Outer对象。

请观察程序运行结果。

代码:

Outer类:

Main类:

结果:

错误信息:

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Outer.java

Error:(6, 8) java: 涉及lab.Outer的循环继承

/Users/admin/Workspace/Java/Hello/src/main/Main.java

Error:(9, 9) java: 找不到符号

符号: 类 Outer

位置: 类 main.Main

Error:(9, 27) java: 找不到符号

符号: 类 Outer

位置: 类 main.Main

Error:(10, 14) java: 程序包Outer不存在

错误是由循环继承造成的,因为内部类Inner是在外部类Outer里面的,如果内部类Inner不在外部类Outer里面就可以,我们来试试。

演示:

请在上例的基础上,添加一个外部类FuOuter,然后在外部类FuOuter里面定义一个内部类Inner,最后让外部类Outer基础自外部类FuOuter里面的内部类Inner。

请观察程序运行结果。

代码:

FuOuter类:

Outer类:

Main类:

结果:

错误信息:

文字版:

/Users/admin/Workspace/Java/Hello/src/lab/Outer.java

Error:(6, 8) java: 需要包含lab.FuOuter.Inner的封闭实例

错误是因为内部类的构造方法必须连接到指向其外部类对象的引用

修改Outer类:

Main类:

结果:

外部类继承内部类时,必须这样写,因为内部类里面必须要有一个它的外部类引用,比如上例中内部类Inner的外部类是FuOuter,这个内部类Inner成为父类的时候,它没有外部类的引用,编译就不通过。

那么以前我们创建外部类的实例时怎么没有看见需要外部类的引用?

那是因为编译器帮你做了,还记得我们以前创建内部类对象之前必须得先创建外部类对象吗?这就是很好的说明了,你想想,我们为什么可以从内部类里面随意使用外部类里面的成员,就是因为我们有外部类对象的引用,当我们需要用到外部类里面的成员时,就会拿着外部类对象去调用对应的成员。

我们再来试试静态内部类作为父类:

FuOuter类:

Outer类:

Main类:

结果:

同样的,子父类特性都有。比如使用super关键字获取父类中的成员。以上展示了外部类继承内部类和静态内部类,抽象内部类和静态抽象内部类其实和内部类、静态内部类差不多,只是有一点特性上的不同而已,这里就不再赘述了。

总结

  • 内部类、静态内部类、抽象内部类和静态抽象内部类可以继承外部类。
  • 内部类、抽象内部类可以继承内部类。静态内部类和静态抽象内部类不可以继承内部类。
  • 内部类、静态内部类、抽象内部类和静态抽象内部类可以继承静态内部类。
  • 内部类、抽象内部类可以继承抽象内部类。静态内部类和静态抽象内部类不可以继承抽象内部类。
  • 内部类、静态内部类、抽象内部类和静态抽象内部类可以继承静态抽象内部类。
  • 外部类不能继承本类中内部类、静态内部类、抽象内部类和静态抽象内部类。
  • 外部类不能继承另一个外部类中的内部类和抽象内部类。
  • 外部类可以继承另一个外部类中的静态内部类和静态抽象内部类。

至此,Java中内部类与继承详细讲解相关内容讲解先告一段落,更多内容请持续关注。

答疑

如果大家有问题或想了解更多前沿技术,请在下方留言或评论,我会为大家解答。

上一章

“全栈2019”Java第七十七章:抽象内部类与静态抽象内部类详解

下一章

“全栈2019”Java第七十九章:类中可以嵌套接口吗?

学习小组

加入同步学习小组,共同交流与进步。

  • 方式一:关注头条号Gorhaf,私信“Java学习小组”。
  • 方式二:关注公众号Gorhaf,回复“Java学习小组”。

全栈工程师学习计划

关注我们,加入“全栈工程师学习计划”。

版权声明

原创不易,未经允许不得转载!

了解更多
举报
评论 0