【JAVA】Java的继承(干货满满)
目录
1.8 protected 关键字(就是与privat和public并列关系)
一:继承(面向对象的关键语法)
把公共的内容,单独提取出来作为父亲,其他个性化的东西,基于“父亲”派生出“子类”个性化的东西放到子类中,这样做可以使代码复用。
1.1 为什么需要继承
java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑
使用Java语言来进行描述,就会设计出: // Dog.java public class Dog{ string name; int age; float weight; public void eat(){ System.out.println(name + "正在吃饭"); } public void sleep(){ System.out.println(name + "正在睡觉"); } void Bark(){ System.out.println(name + "汪汪汪~~~"); } } // Cat.Java public class Cat{ string name; int age; float weight; public void eat(){ System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "正在睡觉"); } void mew(){ System.out.println(name + "喵喵喵~~~"); } }通过观察上述代码会发现,猫和狗的类中存在大量重复,
那能否将这些共性抽取呢?面向对象思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。
1.2 继承概念
父类:提取出来的公共代码
子类:个性化代码,继承父类(父类的属性和方法,就能重用起来)
通过父类产生子类的过程,就叫派生
父类派生出来子类 子类继承父类父类叫法:父类 基类、超类 翻译后:parentclass、base class 、 super class
子类叫法:子类 派生类 翻译后: child class derived class 、sub class
这种3v3的关系上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类或超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。
从继承概念中可以看出继承最大的作用就是:实现代码复用,还有就是来实现多态(后序讲)。
1.3:继承的语法
在Java中如果要表示类之间的继承关系,需要借助extends关键字,具体如下:
修饰符 class 子类 extends 父类 { // ... }
注意:
1. 子类会将父类中的成员变量或者成员方法继承到子类中了
2. 子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承了
1.4 父类成员访问
在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?
我先创建了4个类(Dog Cat Test(测试)Animal)
就可以看到在Test类main方法中就可以使用2个子类 一个父类的方法和成员变量
运行:
继承也会出现成员变量用不了:
因为Animal类中的name被private修饰:
修改方案:(将类中属性name改成public 也行 但是不好)
另一种,我们不是创建了getname()方法,就可以直接使用,方法去调用private修饰的成员变量:
如果修饰的成员变量是piblic就可以直接使用name。
1.4.1 子类中访问父类的成员变量
类和父类都出现同一个变量名:
会出现什么情况呢
Dog类:我创建了一个与父类相同的变量,看打印谁。
运行:
第一个红框就是做一个对比;
旺财正在吃骨头 这个都是在父类继承的方法。
然后bark方法我们创建在子类,然后优先使用我们在子类创建的变量name。(就是就近原则)
一般不建议这样,还需要区分变量。
1.4.2 子类中访问父类的成员方法
子类和父类有成员方法相同:
运行:
打印的还是子类的结构。(总结还是优先打印子类的)
【说明】1通过子类对象访问父类与子类中不同名方法时,优先在子类中找,找到则访问,否则在父类中找,找到则访问,否则编译报错。
2通过派生类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表不同(重载),根据调用方法适传递的参数选择合适的方法访问,如果没有则报错;
有时候,确实会出现子类和父类的属性名字相同:是否有办法,显示指定,使用父类的版本?
:可以通过super关键字,指定访问父类的属性
1.5 super关键字
由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成员时,该如何操作?直接访问是无法做到的,Java提供了super关键字,该关键字主要作用:在子类方法中访问父类的成员。
运行:
this 访问子类,super访问父类
(不能在静态使用)super也可以调用方法(还可以用来调用父类构造方法)
运行:
1.6 子类构造方法
父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造方法,然后执行子类的构造方法。
运行:
先打印父类的构造在打印子类
在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。父子父子肯定是先有父再有子,所以在构造子类对象时候 ,先要调用基类的构造方法,将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整 。
注意:
1. 若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
3. 在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。
4. super(...)只能在子类构造方法中出现一次,并且不能和this同时出现
1.7 super和this
uper和this都可以在成员方法中用来访问:成员变量和调用其他的成员函数,都可以作为构造方法的第一条语句,那他们之间有什么区别呢?
【相同点】
1. 都是Java中的关键字
2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在
【不同点】
1 this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用
2. 在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性
3在构造方法中:this(...)用于调用本类构造方法,super(...)用于调用父类构造方法,两种调用不能同时在构造方法中出现
4构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有
1.8 protected 关键字(就是与privat和public并列关系)
在类和对象章节中,为了实现封装特性,Java中引入了访问限定符,主要限定:类或者类中成员能否在类外或者其他包中被访问。
使用范围:
1.8.1:default使用
运行结果:
Test和Test2在同一个包,但是Test3是在另外一个包
因为x是default级别,在其他包的类中无法访问
1.8.2:protected的实际应用
介绍protected:protected这个界别要比刚才谈到的default级别更低一些
有更多的类可以访问。
运行:Test4
运行:Test3
Test4使用继承Test,然后我们就可以使用y,但x不可以,因为x是default属性,不可以在其他包中使用,由此可以protect的范围比default更广,protected可以使变量在其他包(子类)也可以使用。
说一下实际情况:实际开发中,绝大部分情况,都是private和public,甚至有的编程语言,压根没有protected这种权限级别,
1.9继承方式
考虑的是类多了,才会考虑。
但在Java中只支持以下几种继承方式:
多层继承,语法上允许,但是实际开发的时候,如果继承层次太多,影响代码可读性,实际当中4-5就差不多了。
多继承就不行(好像脚踏两只船)所以我们java禁止这种继承
注意:Java中不支持多继承。时刻牢记, 我们写的类是现实事物的抽象. 而我们真正在公司中所遇到的项目往往业务比较复杂, 可能会涉及到一系列复杂的概念, 都需要我们使用代码来表示, 所以我们真实项目中所写的类也会有很多. 类之间的关系也会更加复杂.
但是即使如此, 我们并不希望类之间的继承层次太复杂. 一般我们不希望出现超过三层的继承关系. 如果继承层次太多, 就需要考虑对代码进行重构了.
如果想从语法上进行限制继承, 就可以使用 final 关键字
1.10:final关键字
1:使用final修饰关键字,改变了不能被修改。
final关键可以用来修饰变量、成员方法以及类。
eg:先找个例子
`package object2.finaltest;` `public class Test {` `final int x=10;` `public static void main(String[] args) {` `int x=10;` `System.out.println(x);` `x=20;` `System.out.println(x);` `}` `}`运行结果:
接下来就是final的操作了:
看到第二个x变量直接爆红
爆错原因为无法为最终变量x分配值,因为第一个x已经被final修饰了,(功能就是固定变量的值,无法修改)
还有个eg:
2:使用final修饰类(此时该类就不能被继承)
该类就不能被Test1继承
1.11:继承和组合
和继承类似 , 组合也是一种表达类之间关系的方式 , 也是能够达到代码重用的效果。组合并没有涉及到特殊的语法( 诸如 extends 这样的关键字 ), 仅仅是将一个类的实例作为另外一个类的字段。继承表示对象之间是 is-a 的关系 ,比如:狗是动物,猫是动物组合表示对象之间是 has-a 的关系 ,比如:汽车
汽车和其轮胎、发动机、方向盘、车载系统等的关系就应该是组合,因为汽车是有这些部件组成的。
![]()
这就是组合,每一个部分拼凑成猫。
组合和继承都可以实现代码复用,应该使用继承还是组合,需要根据应用场景来选择,一般建议:能用组合尽量用组合。
二:总结
本文系统介绍了Java中的继承机制。继承通过extends关键字实现,允许子类复用父类的属性和方法,达到代码复用目的。文中详细讲解了继承的语法、super关键字的使用、父类成员访问规则、子类构造方法调用顺序等核心概念。同时比较了super和this的区别,介绍了protected关键字的作用范围。文章还指出Java不支持多继承,建议继承层次不超过3-5层,并介绍了final关键字限制继承的特性。最后对比了继承与组合的关系,指出组合表示has-a关系而继承表示is-a关系,建议优先使用组合。继承是面向对象编程实现代码复用和多态的重要机制。
更多推荐































所有评论(0)