毕向东Java基础教程-继承【上】

概述

  • 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承单独的类即可。
  • 多个类可以称为子类,单独的类称为父类或者超类。
  • 子类可以访问父类中的<font color="#FF0000">非私有的</font>属性和行为。
  • 通过extends关键字让类与类之间产生继承关系。
    class SubDemo extends Demo{}
  • 继承的好处:
    继承的出现提高了代码的复用性。
    继承的出现让类与类之间产生了关系,提供了多态的前提。

特点

  • Java中支持单继承,不支持多继承
    一个子类只能有一个直接父类,否则若多个父类中有相同成员,会产生调用的不确定性。

    class SubDemo extends Demo{} //ok
    class SubDemo extends Demo1,Demo2...{} //error
    
  • Java支持多层继承(继承体系)

    class A{}
    class B extends A{}
    class C extends B{} 
    

    当要使用一个继承体系时:
    1)查看该体系中的顶层类,了解该体系的基本功能
    2)创建体系中的最子类对象,完成功能的使用

  • 什么时候定义继承?
    当类与类之间存在着所属("is a")关系的时候,就定义继承。如xxx是yyy的一种,则xxx extends yyy。或者判断父类中的功能是否子类都应该具备,若有些不具备,则不存在继承。不要仅为了获取其他类中某个功能而去继承 。

super关键字

this和super的用法很相似。

  • this代表一个本类对象的引用;super代表一个<font color="#FF0000">父类空间</font>(注意并不是代表父类对象,如下代码,从未定义过父类对象,子类之所以可以获取父类的内容,是因为其持有super引用)。

  • 当本类中的成员和局部变量同名用this区分;当子父类中的成员变量同名用super区分父类(如果不使用super,则默认调用子类自己的成员变量),子类要调用父类构造函数时,可以使用super关键字。

    Example1

    public class Father 
    {    
        int num = 4;
    }
    class Son extends Father{
        int num = 5;
        void show()
        {
            System.out.println(this.num+"..."+super.num);
        }
    }
    class Demo
    {
        public static void main(String[] args)
        {
            Son s = new Son();
            s.show();
        }
    }
    

    父类比子类先加载。

注意:
问题:父类中的私有内容,子类是否具备——实际上子类对于父类中私有的成员变量是继承了的,即定义子类对象时,在堆中存有父类的私有成员变量(上图堆中fu的方框内),只是不能直接访问,所以确切地说,应该是子类中不能直接地访问父类中的私有内容。

Example2

class Person
{
    private String name;
    private int age;

    Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    public int getAge() {return age;}
    public void setAge(int age) {this.age = age;}
}

class Student extends Person
{
    Student(String name, int age)
    {
        super(name, age);//调用父类的构造函数
    }
}
class Worker extends Person
{
    Worker(String name, int age)
    {
        super(name, age);//调用父类的构造函数
    }
}

函数覆盖(Override)

  • 函数覆盖发生在父类与子类之间,其函数名、参数类型、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做函数覆盖。
  • 父类中的私有方法不可以被覆盖。
  • 在子类覆盖方法中,继续使用被覆盖的方法可以通过super.函数名获取。
  • 覆盖注意事项:
    覆盖时,子类方法权限一定要大于等于父类方法权限。
    静态只能覆盖静态,或被静态覆盖(非静态不能覆盖静态,静态不能覆盖非静态,否则会报编译错)。
  • 覆盖的应用:
    当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样即沿袭了父类的功能,又定义了子类特有的内容。

子类的实例化过程

注意构造函数不会继承更不会覆盖(首先函数名都不一样...
子类的实例化过程:子类中所有的构造函数默认都会访问父类中空参数的构造函数(因为每一个构造函数的第一行都有一条默认的语句super();之所以会有这样一条默认语句,是因为子类继承了父类,获取到了父类中的内容(属性),所以在使用父类内容之前,要先明确父类是如何对这些数据初始化的)。

public class Father 
{
    public Father()
    {
        System.out.println("Father run");
    }
}
class Son extends Father
{
    public Son()
    {
        //super(); //默认会调用父类的空参构造函数
        System.out.println("Son run");
    }
}

当父类中没有空参数的构造函数时,子类的构造函数必须通过this或者super语句指定要访问的构造函数。
注意:super语句必须要定义在子类构造函数的第一行,因为父类的初始化动作要先完成。
如果子类构造函数中使用this调用了本类构造函数,那么就没有super了,因为super和this都只能定义在第一行。但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数,即子类构造函数中至少有一个访问父类构造函数。

public class Father 
{
    public Father(int num)
    {
        System.out.println("Father run");
    }
}
class Son extends Father
{
    public Son()
    {
        this(4);
    }

    public Son(int num)
    {
        super(num);
        System.out.println("Son run");
    }

}

注意,类默认的空参构造函数的修饰符与类保持一致。

class Demo
{
    /*
    Demo()
    {
        super(); //父类为Object
        return;
    }
    */
}

Example1:子类的实例化过程

public class Father {
    Father()
    {
        show();
    }
    public  void show()
    {
        System.out.println("father show");
    }
}
class Son extends Father
{
    int num = 8;
    Son()
    {
        super();
        //分水岭
        System.out.println("Son run..." + num);
    }

    public void show()
    {
        System.out.println("Son show..." + num);
    }
}
class Demo
{
    public static void main(String[] args)
    {
        Son s = new Son();
        s.show();
    }
}

输出结果为:

Son show...0
Son run...8
Son show...8

内存图解:

默认初始化,成员变量num=0;显示初始化,成员变量num=8。
默认初始化后,执行super(),经过父类构造函数初始化,再进行自己的显示初始化,最后是自己的构造函数初始化。

注意,若子类当中有构造代码块,则其初始化的过程为:

一个对象的实例化过程:

Person p = new Person();
1、JVM读取指定路径下的Person.class文件,如果该类有直接父类,先加载Person的父类,再加载Person进内存;
2、在堆内存中开辟空间,分配地址;
3、在堆的对象空间中,对对象中的属性进行默认初始化;
4、调用对应的构造函数进行初始化;
5、在构造函数中,先调用父类的构造函数进行初始化;
6、父类初始化完毕后,再对子类的属性进行显示初始化;
7、构造代码块初始化;
8、进行子类构造函数的特定初始化;
9、初始化完毕后,将地址值赋值给引用变量(不一定是在栈中,如下)。

class Demo
{
    Person p = new Person(); //在堆中
}

final关键字

  • final可以修饰类,方法,变量。
  • final修饰的类不可以被继承。(继承弊端:打破了封装性。)
  • final修饰的方法不可以被覆盖。(可以用于在父类中,若有几个方法不希望被复写时)
  • final修饰的变量是一个常量,只能被赋值一次。(用于在类中值不会变化的,命名方式为所有字母大写,单词之间用下划线连接;为什么要用final修饰变量,其实在程序中若一个数据是固定的,那么直接使用这个数据就可以了,但是这样阅读性差,所以加上final)
  • 内部类只能访问被final修饰的局部变量。

Example1

class Person
{
    final int x;
}
class FinalDemo
{
    public static void main(String[] args){
        new Person();
    }
}

编译错误:可能尚未初始化变量x(指的显示初始化)。
注意:变量若是有final修饰符,则一般都为静态:static final int x = 7,每个对象的值都一样。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容