JAVA手记(九)面向对象编程——承继

介绍:java的核心内容是面向对象编程的。大家将实际中客观现实的一切都当作目标,进一步获取目标的相同特性和方式,产生类。假如获取的类具备同样的特性和方式,大家是不是会进一步获取他们?大家今日必须承继专业知识。

一,JAVA承继:

1.承继的定义:

承继java面向对象设计技术性是一个根基,因为它容许建立分层次类。

承继派生类承继父类的特点和个人行为,使派生类目标(案例)具备父类的案例字段名和方式,或是派生类承继父类的方式,使派生类具备与父类同等的个人行为。

大家用现实生活中的事例来表述:

java中的继承是什么-java基本数据类型-第1张图片小兔子和羊是食草动物,而狮子座和小豹子是肉食动物。

食草动物和肉食动物全是小动物。

因此承继必须合乎的相互关系是:is-a,父类更一般,派生类更实际。

食草动物和肉食动物尽管都归属于小动物,但他们的特性和个人行为是不一样的,因而派生类不仅有爸爸妈妈的关联性,也是有自身的特性。

2.承继的英语的语法:

承继是根据关键词extends完成的,全部的类都是以java.lang.object承继的,假如一个类沒有文化的关键词,默认设置会承继object的先祖类(这一类在java.lang库中,因此不用导进)。

派生类 extends 父类{ //特性和方式省去}

如果我们用上边的事例来学习培训承继:

父类:

package cn.hz;/** * @author hz * @version 1.0 * * 父类:动物的分类 */public class Animal { //特性和方式省去...}

派生类:(以食草动物为例子,别的省去)

package cn.hz;/** * @author hz * @version 1.0 * * 派生类:食草动物,承继于小动物父类 */public class Herbivore extends Animal { //特性和方式省去...}

3.承继的应用:

A类承继B类时,能够由A类立即建立,还可以根据引入父类偏向派生类。

派生类A extends 父类B{...}

建立派生类目标的手段1:

派生类A 派生类目标=new 派生类A();

比如,在上例中,建立食草动物a:

Herbivore a=new Herivore();

建立派生类目标的方式2:

父B 派生类目标=new 派生类A();

比如,在上例中,建立食草动物a:

Animal a=new Herivore();

4.承继的实际意义:

看了承传的基本概念和英语的语法,许多同学们很有可能会有一个疑惑?那么我为何要用承继呢?使我们举个事例一起来看看承继和应用的益处。

用上边的事例开发设计小动物,在其中小动物是狗和小企鹅,规定如下所示:

狗:特性(呢称,身心健康值,友好度,种类),方式(打印信息,获得和设定有关特性,搭建方式)。

小企鹅:特性(呢称,身心健康值,友好度,性別),方式(打印信息,获得和设定有关特性,搭建方式)。

类图如下所示:

java中的继承是什么-java基本数据类型-第2张图片编码如下所示:

package cn.hz;/** * @author hz * @version 1.0 * * 狗的类 */public class Dog { private String name; //呢称 private Integer health; //身心健康值 private Integer love; //友好度 private String strain; //种类 public Dog() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getHealth() { return health; } public void setHealth(Integer health) { this.health = health; } public Integer getLove() { return love; } public void setLove(Integer love) { this.love = love; } public String getStrain() { return strain; } public void setStrain(String strain) { this.strain = strain; } public void print(){ System.out.println("狗的基本资料:...省去"); }}package cn.hz;/** * @author hz * @version 1.0 */public class Penguin { private String name; //呢称 private Integer health; //身心健康值 private Integer love; //友好度 private String sex; //性別 public Penguin() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getHealth() { return health; } public void setHealth(Integer health) { this.health = health; } public Integer getLove() { return love; } public void setLove(Integer love) { this.love = love; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public void print(){ System.out.println("小企鹅信息内容:...省去"); }}

根据对类图和编码的数据分析,大家发觉里面写的有两个难题:

编码存有很多沉余,狗和小企鹅拥有相同的特性name,health,love和打印出方式,反复编码太多;编码扩展性不高,假如如今必须加上一个新的小动物猫,必须将全部特性所有再次撰写;

大家应用承继来提升上边的编码。

类图如下所示:

java中的继承是什么-java基本数据类型-第3张图片编码如下所示:

package cn.hz;/** * @author hz * @version 1.0 * * 父类:动物的分类 */public class Animal { private String name; //呢称 private Integer health; //身心健康值 private Integer love; //友好度 public Animal() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getHealth() { return health; } public void setHealth(Integer health) { this.health = health; } public Integer getLove() { return love; } public void setLove(Integer love) { this.love = love; } public void print(){ System.out.println("小动物信息内容:...省去"); }}package cn.hz;/** * @author hz * @version 1.0 * * 狗的类 */public class Dog { private String strain; //种类 public String getStrain() { return strain; } public void setStrain(String strain) { this.strain = strain; }}package cn.hz;/** * @author hz * @version 1.0 */public class Penguin { private String sex; //性別 public void setSex(String sex) { this.sex = sex; }}

提升后,大家获取狗和小企鹅的相同特性放进父类,而派生类只撰写自身特有的特性和公式计算,解决了编码的沉余难题,提升了编码的扩展性。

5.java承继方法:

Java 不兼容多继承,只适用单承继java适用多种承继,能够完成承继链,如以上食草动物承继小动物,小兔子承继食草动物java中的继承是什么-java基本数据类型-第4张图片

6。承继特点:

派生类的特性和方式对父亲类而言并不是公有制的。派生类能够有自已的特性和方式,换句话说,派生类能够拓展父类。派生类可以用自身的方法完成父类的方式。Java的承继是单一承继,但能够数次承继。单一承继代表着一个派生类只有承继一个父类。多种承继就是指,例如B类承继A类,C类承继B类,那麼依照关联,B类是C类的父类,A类是B类的父类,这也是区分于C 承继的一个特性。它增加了类中间的藕合(承继的缺陷,高藕合会造成编码中间更紧凑的衔接和更差的编码自觉性)。

二。承继的综合性实例:

因为面向对象编程环节,定义上的物品很抽象性,因此许多学员意见反馈学习培训的过程中都很清楚,可是具体应用的情况下却很愚昧。在这里一章中,大家根据经典案例,有意加重对承继的了解:

编码如下所示:B类承继了A类,建立了B类的2个目标,最终的实行結果是啥?为什么呢?

package cn.hz;/** * @author hz * @version 1.0 */public class A { public A(){ System.out.println("A的构造函数"); } static{ System.out.println("A的静态数据块"); } { System.out.println("A的动态块"); }}package cn.hz;/** * @author hz * @version 1.0 */public class B extends A { public B(){ System.out.println("B的构造函数"); } static{ System.out.println("B的静态数据块"); } { System.out.println("B的动态块"); }}package cn.hz;/** * @author hz * @version 1.0 */public class TestAB { public static void main(String[] args) { //创建对象 B b=new B(); B b1=new B(); }}

剖析:

上边的编码B承继了A,最终建立了2个B目标。最先,我们知道一个类必须先载入这一类来建立一个目标。针对一个类,有静态数据块(复位类),动态块(复位目标建立)和构造函数(复位由构造函数建立的目标)。她们的实行次序是:

静态数据块-动态块-构造函数。

假如2个类中间存有承继关联,派生类在创建对象的时候会启用父类相匹配的构造方法,在应用构造方法创建对象以前会载入类,父类的全部静态数据块也会被启用。可是,务必留意的是,创建对象时,父类的动态块先进行复位,随后实行构造方法,再根据派生类的动态块进行派生类复位,随后根据构造方法创建对象,即:

父静态数据块-派生类静态数据块-父动态块-父构造函数-派生类动态块-派生类构造函数。

融合编码,大家发觉建立了2个目标。这个时候,就需要注意了。载入类时,静态数据块不容易在复位的中后期实行,但动态块和构造函数将在每一个目标建立后实行。全部最后实行結果如下所示:

java中的继承是什么-java基本数据类型-第5张图片汇总:

这一实例的关键是调查大伙儿对目标建立和传承的了解,能够根据开展形变演试来汇总剖析这一实例。

三,方式调用:

根据承继,能够处理编码沉余的难题,提升编码的扩展性。可是在具体开发设计中,大家发觉父类设定的方式派生类不适合,必须调用?那麼什么叫调用呢?调用时必须注意什么?

1.调用的界定:

调用派生类调用父类的可浏览方式的完成全过程,传参和主要参数不可以变更。也就是机壳不会改变,核心调用!

调用的益处是派生类能够按照必须界定自身的个人行为。换句话说,派生类能够按照必须完成父类的方式。

调用方式不可以引起新的查验出现异常或比例写方式申明的出现异常更普遍的出现异常。比如,父类的一个方式申明了一个check Exception IOException,可是在调用这一步骤时,它不可以抛出去Exception,由于Exception是IOException的父类,只有抛出去IOException的派生类出现异常。

2.调用的实际应用:

和上边的事例一样,在animal类中界定了一个打印出方式,可是不一样的派生类有不一样的打印出內容,因此必须调用。编码如下所示:

public class Animal{ //特性省去...public void print(){//编码省去...}}public class Dog extends Aniaml{//特性省去 @Override public void print() { //派生类实际完成 }}

根据之前的编码,大家看到了一些难题:

父类的打印出方式的方式完成体沒有一切实际意义,是不是能够省去?–(实际见内部类抽象方法章节目录详尽解读)派生类调用父类的同名的方式,有哪些规定?–(见后边调用标准)

3.调用标准:

主要参数目录与被调用方式的主要参数目录务必完全一致。回到种类与被调用方式的回到种类可以不同样,可是务必是父类传参的派生类(java5 及更早版本号回到种类要一样,java7 及高些版本号能够不一样)。访问限制不可以比父类中被调用的办法的访问限制更低。比如:假如父类的一个方式被申明为 public,那麼在派生类中调用该方式就不可以申明为 protected。父类的组员方式只有被它的派生类调用。申明为 final 的方式不被调用。申明为 static 的方式不被调用,可是可以被再度申明。派生类和父类在同一个库中,那麼派生类能够调用父类全部方式,除开申明为 private 和 final 的方式。派生类和父类没有同一个库中,那麼派生类只可以调用父类的协议为 public 和 protected 的非 final 方式。调用的方式可以抛出去一切非强制性出现异常,不管被调用的办法是不是抛出异常。可是,调用的方式不可以抛更新的强制出现异常,或是比被调用方式申明得更普遍的强制出现异常,相反则能够。构造函数不可以被调用。假如不可以承继一个类,则不可以调用此类的方式。

四,equals方式调用:

1.为何调用equals方式:

大家都在上面详尽诠释了方式的调用。使我们看一下现实生活中的一个事例:

界定学员类型,学员,特性id,名字;假如两人的身份证号码和名字同样,那麼在现实生活中便是同一个人,较为的結果应该是确实。使我们看一下如果我们应用java编码会产生哪些。

package cn.hz;/** * @author hz * @version 1.0 * 界定学员类 */public class Student { private Integer id; //特性:身份证号码 private String name; //特性:名字 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}package cn.hz;/** * @author hz * @version 1.0 */public class StudentTest { public static void main(String[] args) { //建立学员目标1 Student student1=new Student(); student1.setId(123456); student1.setName("张三"); //建立学员目标2 Student student2=new Student(); student2.setId(123456); student2.setName("张三"); System.out.println("2个学员目标是不是为同一个:" student1.equals(student2)); }}

大家根据运作获得的结论是不正确的:

java中的继承是什么-java基本数据类型-第6张图片显而易见,这一結果不符你们的实际。为啥java中会经常出现那样的結果?根据剖析,我们知道全部的java类都是以Object父类承继过来的,大家采用的equals较为方式事实上便是Object类。根据API找寻最底层编码,我们知道Object中的equals源码如下所示:

java中的继承是什么-java基本数据类型-第7张图片实质上是用= = =的。= =较为堆中2个目标建立的详细地址,結果自然是假的。那麼怎么让大家学员班的比较分析法合乎大家的具体必须呢?这规定我们在父类Object中再次创建equals方式。

2.调用equals方式的实际完成:

根据剖析,我们可以了解具体对比的那些状况:

假如2个目标在堆里层详细地址一样,则毫无疑问相同假如2个目标的种类不同样,则毫无疑问不相同假如详细地址不一样,种类同样,2个目标的全部特性都同样,则2个目标相同

编码完成如下所示:

package cn.hz;/** * @author hz * @version 1.0 * 界定学员类 */public class Student { private Integer id; //特性:身份证号码 private String name; //特性:名字 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } /** * 调用equals方式 * @param obj * @return */ @Override public boolean equals(Object obj) { //假如2个目标详细地址同样,则2个目标目标內容一定同样; if(this==obj){ return true; } //假如2个目标的种类不一样,则2个目标內容毫无疑问不一样, //instanceof表明判断左边目标是不是右边种类,传参为boolean if(!(obj instanceof Student)){ return false; } //主要参数为object种类,早已判断种类,则能够明确obj为student种类,为了更好地获得特性,obj变换为student Student o=(Student) obj; //假如2个目标的详细地址不一样,种类同样,假如2个目标的特性值一样则为同一个目标,結果true if(this.id==o.id && this.name.equals(o.name) ){ return true; }else{ return false; } }}package cn.hz;/** * @author hz * @version 1.0 */public class StudentTest { public static void main(String[] args) { //建立学员目标1 Student student1=new Student(); student1.setId(123456); student1.setName("张三"); //建立学员目标2 Student student2=new Student(); student2.setId(123456); student2.setName("张三"); System.out.println("2个学员目标是不是为同一个:" student1.equals(student2)); }}

实行結果为真,如下所示所显示:

java中的继承是什么-java基本数据类型-第8张图片

汇总:

在现实生活中,大家常常必须较为目标。equals方式关键采用较为內容,而= =用以较为详细地址。为了更好地使equals达到大家的具体要求,大家常常必须调用equals方式。

评论(0条)

刀客源码 游客评论