“全栈2019”Java第七十八章:内部类可以继承其他类吗?
难度
初级
学习时间
30分钟
适合人群
零基础
开发语言
Java
开发环境
- JDK v11
- IntelliJ IDEA v2018.3
提示
本教学属于系列教学,内容具有连贯性,本章使用到的内容之前教学中都有详细讲解。
1.复习继承相关知识点
继承是我们的老朋友了,之前我们也学过继承。
这里简单复习一下:
继承只能发生在类与类,接口与接口之间。
类与类之间只能单继承,不能多继承。
接口与接口之间可以多继承。
类与类继承,存在字段的隐藏,实例方法的重写,类方法的隐藏等特性。
类与类之间不能存在循环继承,什么叫循环继承。就是A继承B,B继承C,C再继承A,这就叫循环继承。A继承A也是循环继承。
好了,简单复习了一下继承相关知识点,如果需要深入连接的同学,请点击下面链接:
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学习小组”。
全栈工程师学习计划
关注我们,加入“全栈工程师学习计划”。
版权声明
原创不易,未经允许不得转载!
请先 后发表评论~