16.面向对象进阶:继承,重写,构造器访问,成员访问,this&super

面向对象三大基本特征之二:继承

继承概述

  • 继承是类与类之间的一种关系

  • 多个类继承单独的某个类,多个类就可使用单独的这个类的属性和行为了;Java中子类更强大

  • 多个类称为子类(又称派生类),单独的这个类称为父类(又称基类,或超类)

  • 使用extends关键字实现继承:public class 子类名 extends 父类名()

    public class Student extends People{}
    //表示Student类继承自People类
    
  • 使用继承的好处:提高代码复用,减少代码冗余,增强类的功能扩展性

  • 测试代码:

    package com.java.test;
    
    public class Student2 extends People {
    
        public void study() {
            System.out.println(getName() + "读书学习");
        }
    }
    
    
    package com.java.test;
    
    public class Teacher extends People {
    
        public void teach() {
            System.out.println(getName() + "教书育人");
        }
    
    }
    
    package com.java.test;
    
    public class People {
        private String name;
        private int 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;
        }
    }
    
    
    package com.java.test;
    
    public class TestExtends {
        public static void main(String[] args) {
            Student2 student = new Student2();
            Teacher teacher = new Teacher();
            student.setName("徕卡");
            student.setAge(23);
            teacher.setName("哈苏");
            teacher.setAge(32);
            System.out.println(student.getName() + "\t" + student.getAge());
            System.out.println(teacher.getName() + "\t" + teacher.getAge());
    
            student.study();
            teacher.teach();
        }
    }
    

继承的设计规范,内存运行原理

继承设计规范

  • 子类们相同特征(共性属性,共性方法)放在父类中定义;子类独有的属性和行为应该定义在子类自己里面

    如果子类独有的属性,行为定义在父类中,会导致其他子类也会得到这些属性和行为,这不符合面向对象逻辑

内存运行原理

  • 首先加载主方法时会在堆内存中开辟空间,在空间中划分出一块父类空间(称为super)和一块子类空间(称为this)
  • image.png

继承的特点(面试热点)

  1. 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器

    • 子类有自己的构造器,父类构造器用于初始化父类对象

    • 子类是否可以继承父类私有的成员(存在争议)

      • Java官方文档的解释:子类不能继承父类的私有成员,但是如果子类中公有的方法影响到了父类私有成员,那么私有成员是能够被子类使用的

      • 个人理解:当存在一个子类对象时,在内存空间上:子类对象继承的super中私有成员被继承但是无法直接访问

      image.png
    • 子类是否可以继承父类的静态成员(存在争议)

      • 子类可以直接使用父类的静态成员(共享并非继承)

        静态的成员属于类本身,且静态只会加载一次,静态是属于父类的关系,即子类不能继承父类的静态成员,这种关系是父类向子类共享静态成员,子类可以共享访问使用静态成员,但是并非继承关系

  2. Java是单继承模式,一个类只能继承一个直接父类

  3. Java不支持多继承,但是支持多层继承

  4. Java中所有的类都是Object类的子类

继承后:成员变量,成员方法的访问特点

  • 在子类方法中访问成员变量,成员方法时,满足:就近原则

    就近原则:

    • 先子类局部范围找
    • 然后子类成员范围找
    • 然后父类成员范围找,如果父类范围还没有找到则报错
  • 使用super关键字访问父类的成员

  • 当子类和父类中出现了同名的方法,会优先使用子类同名方法,此时要使用父类中的同名方法的办法是在子类中建立中转方法

  • 测试代码

    package com.java.test;
    
    public class ExtendsDemo {
        public static void main(String[] args) {
            Wolf w = new Wolf();
            System.out.println(w.name);
            w.showName();
            w.dance();  //触发子类的dance方法
            //  调用中转方法来触发父类的dance方法
            w.sing();
        }
    }
    
    class Animal {
        public String name = "触发父类";
    
        public void dance() {
            System.out.println("父类dance方法触发");
        }
    }
    
    class Wolf extends Animal {
        public String name = "触发子类";
    
        public void showName() {
            String name = "局部名称";
            System.out.println(name);   //  局部名称
            System.out.println(this.name);  //  触发子类
            System.out.println(super.name); //  触发父类
        }
    
        public void dance() {
            System.out.println("子类dance方法触发");
        }
    
        public void sing() {
            super.dance();  //sing为中转方法
        }
    }
    

继承后:方法重写

  • 在继承体系中,子类出现了和父类中一模一样的方法声明,我们称子类这个方法是重写的方法

  • 方法重写的应用场景:

    • 当子类需要父类的功能,但父类的该功能不完全满足自己的需求时
    • 子类可以重写父类中的方法
  • @Override重写注解:

    • 放在重写后的方法上,作为重写是否正确的校验注解
    • 加上该注解后如果重写错误,编译阶段会出现错误提示(例如方法名不一致时,可以防止运行的是新方法而不是重写)
    • 建议重写方法都加上@Override注解,代码安全,优雅!
  • 方法重写注意事项和要求

    • 重写方法的名称,形参列表必须与被重写方法的名称和参数列表一致

    • 私有方法被能重写(因为私有方法本身也不可以被访问)

    • 子类重写方法时,访问权限必须大于或等于父类

      按公开级别从大到小依次是:public > protected > 缺省

    • 子类不能重写父类的静态方法,如果重写会报错

      因为静态方法属于类,而重写的前提就是对被重写的方法拥有所有权,子类不曾拥有父类静态方法,所以对子类而言不存在对父类静态方法重写这个说法

  • 测试代码:

    package com.java.test;
    
    public class ReWrite {
        public void run() {
            System.out.println("跑步");
        }
    
        public void play() {
            System.out.println("打球");
        }
    
        public static void main(String[] args) {
            ReWrite2 re = new ReWrite2();
            re.run();
            re.play();
        }
    }
    
    class ReWrite2 extends ReWrite {
        @Override
        public void run() {
            super.run();    //重写时保留父类原方法中的功能
            System.out.println("马拉松");  //对父类中的方法进行重写
        }
    
        @Override
        public void play() {
            super.play();
            System.out.println("锦标赛");
        }
    }
    
    

继承后:子类构造器的特点

  • 子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己

    • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据
    • 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化
  • 如何调用父类构造器

    • 子类构造器的第一行语句默认都是:super(),不写也存在
  • 测试代码:

    package com.java.test;
    
    public class constructor {
        public static void main(String[] args) {
            worker w = new worker();
            /*
            父类构造器被触发
            子类构造器被触发
             */
    
        }
    }
    
    class boss {
        public boss() {
            System.out.println("父类构造器被触发");
        }
    }
    
    class worker extends boss {
        public worker() {
            super();    //默认的,写不写都有,默认就是找父类无参构造器
            System.out.println("子类构造器被触发");
        }
    }
    

继承后:子类构造器访问父类有参构造器

  • super调用父类有参构造器的作用:

    • 初始化继承自父类的数据
  • 父类中没有无参构造器,只有有参构造器,会出现什么情况

    • 报错,因为子类默认调用父类的无参构造器
  • 如何解决

    • 子类构造器中可以通过书写super(...),手动调用父类的有参构造器
  • 测试代码:

    package com.java.test;
    
    public class Constructor1 {
        public static void main(String[] args) {
            American a = new American("张三", 21, "男");
            System.out.println(a.getName());
            System.out.println(a.getAge());
            System.out.println(a.getSex());
        }
    }
    
    class English {
        private String name;
        private int age;
    
        // 有参构造器引发继承报错,选择了有参构造器时,建议加上无参构造器
        // 或者子类手动调用父类的有参构造器,即便如此,实际开发仍建议加上无参构造器
        public English(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 American extends English {
        private String sex;
    
        // 手动调用父类的有参构造器
        public American(String name, int age, String sex) {
            super(name, age);
            this.sex = sex;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    }
    
    

this,super使用总结

关键字 访问成员变量 访问成员方法 访问构造方法
this this.成员变量
访问本类成员变量
this.成员方法
访问本类成员方法
this(...)
访问本类构造器
super super.成员变量
访问父类成员变量
super.成员方法
访问父类成员方法
super(...)
访问父类构造器
  • this:代表本类对象的引用
  • super:代表父类存储空间的标识
  • 对于this(...)访问本类构造器

    案例代码:

    pubic class Student{
        private String schoolName;
        private String name;
        
        public Student(String name){
            this(name, "奥利奥")
        }
        
        public Student(String name, String schoolName){
            this.name = name;
            this.schoolName = schoolName;
        }
    }
    
  • this(...)和super(...)使用注意点
    • 子类通过this(...)去调用本类的其他构造器,本类其他构造器会通过super手动调用父类的构造器,最终还是会调用父类构造器的
    • this和super都只能放在构造器的第一行,所以也就意味着二者不可以共存在一个构造器中
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容