【Java SE】面向对象三大特性之继承(二)

简介: 【Java SE】面向对象三大特性之继承

🐳 子类构造方法:

子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。

1. //Car.java
2. public class Car {
3. int a;
4. int b;
5.     String name;
6. 
7. public Car(){
8.         System.out.println("基类构造方法");
9.     }
10. 
11. }
12. 
13. //BMW.java
14. public class BMW extends Car{
15. int b;
16. int c;
17. public BMW(){
18.         System.out.println("子类构造方法");
19.     }
20. 
21. 
22. }
23. 
24. //Test.java
25. public class Test {
26. public static void main(String[] args) {
27.      BMW bmw=new BMW();
28.     }
29. }

子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。

注意:

1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现

🐳super和this的区别:

🐳 代码块在继承关系中的执行顺序:

1. //Car.java
2. public class Car {
3. int a;
4. int b;
5.     String name;
6.     {
7.         System.out.println("父类实例代码块执行");
8.     }
9. 
10. static {
11.         System.out.println("父类静态代码块执行");
12.     }
13. public Car(){
14.         System.out.println("基类构造方法执行");
15.     }
16. 
17. }
18. //BMW.java
19. public class BMW extends Car{
20. int b;
21. int c;
22.     String name;
23.     {
24.         System.out.println("子类实例代码块执行");
25.     }
26. 
27. static {
28.         System.out.println("子类静态代码块执行");
29.     }
30. public BMW(){
31.         System.out.println("子类构造方法");
32.     }
33. 
34. 
35. }
36. //Test.java
37. public class Test {
38. public static void main(String[] args) {
39.      BMW bmw=new BMW();
40.     }
41. }

当我们第二次实例化对象的时候,我们可以清楚的看到:

1. public class Test {
2. public static void main(String[] args) {
3.      BMW bmw=new BMW();
4.      System.out.println("第二次实例化子类对象:");
5.      System.out.println("==================================");
6.      BMW bmw1=new BMW();
7.     }
8. }

通过分析执行结果,得出以下结论:
1、父类静态代码块优先于子类静态代码块执行,且是最早执行
2、父类实例代码块和父类构造方法紧接着执行
3、子类的实例代码块和子类构造方法紧接着再执行
4、第二次实例化子类对象时,父类和子类的静态代码块都将不会再执行

🐳protected 关键字

在封装的那一篇开头介绍了访问控制修饰符:【Java SE】面向对象三大特性之封装

感兴趣的可以再去了解一下。

这边建立了2个不同的包:

其中一个是同一个包中的2个类,另一个类在另一个包中:

首先在同一个包中:

1. package TestDemo;
2. //A.java
3. public class A {
4. public int a;
5. private int b;
6. protected int c;
7. int d;
8. }
9. //B.java
10. package TestDemo;
11. 
12. public class B extends A{
13. 
14. public void method(){
15. 
16. super.a=20;
17. super.b=100;
18. super.c=30;
19. super.d=40;
20. 
21. 
22. }
23. 
24. }

虽然不能访问,但是也继承了父类的b成员变量。

现在是两个包中的:

1. package TestDemo;
2. //A.java
3. 
4. public class A {
5. public int a;
6. private int b;
7. protected int c;
8. int d;
9. }
10. //C.java
11. package TestDemo1;
12. 
13. import TestDemo.A;
14. 
15. public class C extends A {
16. public void method(){
17. 
18. super.a=20;
19. super.b=100; //编译报错,父类中private成员在不同包子类中不可见
20. super.c=30;// 父类中protected修饰的成员在不同包子类中可以直接访问
21. super.d=40;// 父类中默认访问权限修饰的成员在不同包子类中不能直接访问
22. 
23.     }
24. }

注意:我们在使用的时候应该尽可能的使用 比较严格的访问权限. 例如如果一个方法能用 private, 就尽量不要用 public.

🐳继承方式

继承方式有单继承,多层继承和不同类继承同一个类。

一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.

如果想从语法上进行限制继承, 就可以使用 final 关键字

🐳final 关键字

final关键可以用来修饰变量、成员方法以及类

1. 修饰变量或字段,表示常量(即不能修改)

2. 修饰类:表示此类不能被继承

3. 修饰方法:表示该方法不能被重写

🐳重写

当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。

要想调用父类中被重写的方法,则必须使用关键字 super。

1. public class Animals {
2. public void call(){
3.         System.out.println("动物叫...");
4.     }
5. }
6. 
7. 
8. public class Cat extends Animals{
9. @Override
10. public void call() {
11.         System.out.println("喵喵喵...");
12.     }
13. }
14. 
15. 
16. public class Dog extends Animals{
17. @Override
18. public void call() {
19. super.call();
20.     }
21. 
22. public static void main(String[] args) {
23. Animals dog = new Dog();
24.         dog.call();//动物叫...
25. Animals cat = new Cat();
26.         cat.call();//喵喵喵...
27.     }
28. }

🐳继承与组合

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物
组合表示对象之间是has-a的关系,比如:汽车有发动机,轮胎等等组成

1. class D{
2. 
3. }
4. class E{
5. 
6. }
7. //F由D,E构成(组合)
8. class F{
9. private D d; // 可以复用D的属性和方法
10. private E e; // 可以复用E的属性和方法
11. 
12. }

组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合。

相关文章
|
9天前
|
缓存 运维 Java
Java静态代码块深度剖析:机制、特性与最佳实践
在Java中,静态代码块(或称静态初始化块)是指类中定义的一个或多个`static { ... }`结构。其主要功能在于初始化类级别的数据,例如静态变量的初始化或执行仅需运行一次的初始化逻辑。
26 4
|
2月前
|
Java
Java 面向对象编程的三大法宝:封装、继承与多态
本文介绍了Java面向对象编程中的三大核心概念:封装、继承和多态。
162 15
|
3月前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
3月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
45 1
|
3月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
120 6
|
4月前
|
Java
在Java中,接口之间可以继承吗?
接口继承是一种重要的机制,它允许一个接口从另一个或多个接口继承方法和常量。
368 60
|
4月前
|
JavaScript 前端开发 Java
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。如果你从我的文章中受益,欢迎关注我,我将持续更新更多优质内容。你的支持是我前进的动力!🎉🎉🎉
41 0
还不明白面向对象? 本文带你彻底搞懂面向对象的三大特征(2024年11月Java版)
|
4月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
55 4
|
5月前
|
Java
java继承和多态详解
java继承和多态详解
75 5
|
6月前
|
Java 编译器
Java——类与对象(继承和多态)
本文介绍了面向对象编程中的继承概念,包括如何避免重复代码、构造方法的调用规则、成员变量的访问以及权限修饰符的使用。文中详细解释了继承与组合的区别,并探讨了多态的概念,包括向上转型、向下转型和方法的重写。此外,还讨论了静态绑定和动态绑定的区别,以及多态带来的优势和弊端。
131 7
Java——类与对象(继承和多态)

热门文章

最新文章