Java面向对象之继承

  • Post author:
  • Post category:java


概念

继承是Java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

继承是面向对象的三大特征之一。继承和现实生活中的“继承”的相似之处是保留一些父辈的特性,从而减少代码冗余,提高程序行效率。

extend关键字

extend本意为”扩展“——> 子类extend父类,描述的是子类在父类基础上进行拓展。

 //classA为父类,classB为子类
 class A {
 }
 class B extends A {
 }
 class C extends B{
 }
 /*当出现classC类,此时classA称为超类或基类,classB类和classC类都是它的派生类*/
 /*画图表示关系:classA <--- classB <--- classC【箭头永远指向父类】*/


注意:不是只要分析出具备相同属性行为,我们就做继承,必须具备类与类之间有is-a关系,我们才会去做继承

单继承

Java中的继承是单继承【在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。】

单继承和多继承的优缺

多继承 优:丰富度的增加,子类既有来自父类A的内容,也有来自于父类B的内容,甚至还有父类

缺:会带来关系复杂度的问题。比如在结构上多继承不可能避免的都会出现网状结构

单继承 优:没有关系复杂度的问题,类与类之间只能形成层次结构清晰的树形图

缺:丰富度会减少

继承细节

父类的哪些内容会被继承

1、父类中的属性会被继承;就算是私有属性也会被继承,只是不能被看到而已.

【访问修饰符控制的是是否能够被直接看到操作到,而不是是否能被继承】

2、父类中的行为也会被继承,与属性是一样的道理。

3、父类的构造方法是不能被子类继承的。

【原因:1、构造方法的名字必须和类名保持一致;{父类的构造方法是父类类名,子类的构造方法是子类类名}。如果构造方法能被继承,那么说名字类里面有一个构造方法,但名字是父类,很明显语法不允许 2、构造方法的作用是产生对象;{父类构造方法产生父类对象,子类构造方法产生子类对象}。如果子类通过继承拥有了父类的构造方法,那么说明子类拥有一个产生父类的方法,伦理不允许】

继承的内存模型

JVM是采用一种或叫做”内存叠加“的方式,来实现继承关系。

当我们产生一个子类对象的时候,JVM是分两步走的:

1、首先调用父类的构造方法,产生一个父类对象部分

2、然后调用子类的构造,在上一步父类对象部分之下叠加上子类特有的部分,从而形成一个完整的子类对象


注意:1、每次new子类只产生了一个子类对象,而不是一个父类对象和子类对象


2、在默认情况下,子类会自动调用的是父类的无参构造:


【解决2的方法:1、养成写公共无参构造的习惯,这本身也是JavaBean的规范 2、如果一定要调用某个带参构造,使用super关键字】

super关键字

super( )与this( )一样,都只能写在构造方法里面,也是只能写在第一句,因此二者不能并存。

super和this对比

1、this( )与super( )区别

this() super()
作用 调用本类的其它构造方法;从而达到本类构造方法的代码可以复用的效果。 与继承无关。 调用父类的指定构造方法;从而达到使用指定的父类构造方法构造子类中的父类对象部分。 与继承有关。
位置 构造方法的第一句;与super()互斥。 构造方法的第一句;与this()互斥。
默认 没有 有,就是无参的super()

2、this.和super.的区别

作用不同

this. —-书写在一个类的内部代码块中,用来调用当前对象的属性和行为 —含义是: 当前对象

super. —-书写在一个类的内部代码块中,用来调用当前对象从父类继承而来的属性或行为—含义:当前对象的父类部分


注意:super.也会受到访问修饰符的限制


总结:1、this.能看到本类自己定义的,也能看到父类继承而来的(但受访问修饰符的限制)


2、super.只能看到从父类继承而来的(但受访问修饰符的限制)


3、通常只用this.


4、调用重写方法的时候super.【super.调用的是子类重写前的方法】【this.调用的是子类重写后的方法】


补充:方法的重写:

子类从父类那里继承了一个方法,然后把这个方法重新实现了


子类把从父类继承而来的方法重新实现一次,方法的重写不是添加一个新的方法,而是把原有的方法实现部分给覆盖调用


方法的重写要求:1、方法名不能变


2、参数列表不能变


3、返回类型不能变


4、 访问修饰符可大 【public > protected > 默认 > private】

重写和重载例子

1、重写:小猫小狗 eg:小狗会吃东西,小猫也会吃东西但吃的东西不一样

重载:主人喂养小猫小狗

2、重写:语文老师,数学老师都有上课的行为,语文老师用白板,数学老师用黑板

重载:语文老师上课有黑板就用黑板,有白板就用白板

3、重写:上学和上班都有出行的行为,上班的开车出行,上学的公交出行

重载:上班的出行行为,可以开车也可以坐公交

Object类

Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,

子类可以使用 Object 的所有方法



Object 类位于 Java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。

方法名 含义 学习章节
getclass( ) 获取当前对象的类模板对象【反射章节讲】 反射
hashcode( ) 获取当前对象的哈希值【集合框架中讲】 集合框架
equals( ) 比较两个对象是否相等 方法重写
clone( ) 克隆方法,根据一个已有对象产生一个一模一样的新对象【设计模式中讲】 原型模式
toString( ) 返回一个对象的字符串描述 方法重写
notify( ) 唤醒处于等待中的线程【多线程中讲】 多线程
notifyAll( ) 唤醒处于等待中的全部线程【多线程中讲】 多线程
wait( ) 3个重载的wait方法,让当前线程进入等待方法【多线程中讲】 多线程
finallize( ) 在JDK9之前用来销毁对象的方法 垃圾回收

equals( )方法


要求必须会用,有大量使用

equals( )方法用来判断两个对象是否相等

两个对象是否相等

1、用“ == ”判断是否相等,是判断这两个引用是否指向同一个对象。

2、equal( )方法判断的是不同的对象是否内容相同。

补充:@Override—是Java中注解类型的标记,该标记用来检查方法是否是一个正确的重写

总结equals( )

1、equal( )方法判断的是不同的对象是否内容相同。

2、该方法定义在Object类上,通过继承所有Java类都具有该方法。

3、Object中的equals方法是使用的 “ == ”,所以各个具体的子类都需要对equals方法进行重写,从而实现各自判断相等的规则。

toString( )方法

作用是返回当前对象的字符串描述。

toString( )方法在Object中的默认实现是返回一个:类的限定名@对象的哈希值


注意:toString( )方法还有一个特点就是当我们对一个对象进行字符串操作的时候,会默认调用这个对象的toString方法,不用手工调用

finalize( )方法

最多在面试中用到

finaliz( )方法和构造方法组成一对的,构造方法的作用是产生对象,finalize方法作用是销毁对象。


销毁对象会涉及到很多底层操作,先人预先在OBject中写好了,通过继承让我们自定义的每个类都具有这种方法,所以不用去重写

eg:面试题:finalize( )方法是谁的方法? 是Object的

不是GC(垃圾回收机制)

finalize( )方法是谁使用的? 是GC在销毁对象的时候使用的。

finalize( )方法能重写吗? 可以,但一般不建议重写,甚至可以用public扩大他的访问修饰符。

【为什么不建议重写】因为销毁对象涉及到很多底层算法和API的使用,应用层程序员并不清楚如何使用API和实现这些算

法。

final 关键字

用法:

1、final关键字修饰变量,但被修饰的变量不能变了,因此变成了常量。


注意:1、这里说的是修饰变量,不仅仅是属性,也包括局部变量,final都可以把这些变量变成常量 2、当属性设置为final的常量的时候,不一定马上赋初始值。



【a、可以实例初始化块赋初始值:无需在定义的时候就确定常量的值是多少 ,可以通过new对象的时候传参,可以给同一个类的不同对象赋不一样的常量值,但此时这个常量值就不能是static,不再是全类共享一个值。如果有多个构造方法,那么每个构造方法都得对常量进行赋值



b、通过构造方法里传参来赋初始值】

2、final关键字修饰方法,但是此方法就不能被重写了 —— 最终方法

3、final关键字修饰类,但被修饰的类不能被继承 —— 最终类/终态类

方法的重写和重载

方法的重写(Override)

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重写规则

1、参数列表必须完全与被重写方法的相同; 2、返回类型必须完全与被重写方法的返回类型相同; 3、访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。 4、父类的成员方法只能被它的子类重写。 5、声明为final的方法不能被重写。 6、声明为static的方法不能被重写,但是能够被再次声明。 7、子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。 8、子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。 9、重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。 10、构造方法不能被重写。 11、如果不能继承一个方法,则不能重写这个方法。

方法的重载(Overload)

重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

重载规则:

1、被重载的方法必须改变参数列表(参数个数或类型或顺序不一样); 2、被重载的方法可以改变返回类型; 3、被重载的方法可以改变访问修饰符; 4、被重载的方法可以声明新的或更广的检查异常; 5、方法能够在同一个类中或者在一个子类中被重载。 6、无法以返回值类型作为重载函数的区分标准。

重写与重载直接的区别

重写:有父子类,重写方法

重载:在同一个类中,相同的方法名传入不同的参数

区别点 重载方法 重写方法
参数列表 必须修改 一定不能修改
返回类型 可以修改 一定不能修改
异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常
访问 可以修改 一定不能做出更严格的限制(可以降低限制)

内存图


深入理解Java内存(图解堆栈) – 万物为铜 – 博客园 (cnblogs.com)

[]



版权声明:本文为niuniu1227原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。