当前位置: 首页 > news >正文

【Java进阶学习 第一篇】Java中的继承

目录

定义

格式

示例

使用场合

成员变量访问特点

成员方法访问特点

方法重写

适用场景

 注意事项

权限修饰符protected

特点

构造方法特点

案例

内存图

综合案例

案例1

super的省略规则

学习视频链接


定义

类和类之间产生父子关系,子类可以直接使用父类非私有的成员

格式

public class子类 extends 父类名{}

示例

public class erzi extends Baba{}

创建类的细节:
一个.java文件中可以编写多个class

但是要:

1.保证类与类之间是平级关系

2.只能有一个被public修饰

package com.yuhan.inherit;

public class inheritDemo1 {
    public static void main(String[] args) {
        Coder coder = new Coder();
        Manager manager = new Manager();
        coder.age = 18;
        manager.name = "张三";
        System.out.println(manager.name + "--" + coder.age);
    }

}
class employee {
    String name;
    int age;
    double salary;
}

class Coder extends employee {
}

class Manager extends employee {
}

上面这种是父类中的非私有成员变量直接可以被子类调用


package com.yuhan.inherit;

public class inheritDemo1 {
    public static void main(String[] args) {
        Coder coder = new Coder();
        Manager manager = new Manager();
        coder.setAge(18);
        manager.setName("张三");
        System.out.println(manager.getName() + "--" + coder.getAge());
    }

}
class employee {
    private String name;
    private int age;
    private double salary;
    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;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

class Coder extends employee {
}

class Manager extends employee {
}

如果遇见父类是JavaBean形式,只有私有变量,我们可以用子类调用父类的getter和setter方法 


使用场合

当类与类之间,存在相同(共性)的内容,并且产生了 is a 的关系,就可以考虑使用继承,来优化代码。

成员变量访问特点

如果我们遇见子类中变量与父类变量重名的现象,正常来说是遵循最近原则,会先运行子类中的成员变量。如果我们需要调用父类中的变量,可以使用super关键字!

public class inheritDemo2 {
    public static void main(String[] args) {
        Erzi e = new Erzi();
        e.method();
    }
}

class Baba {
    int age = 18;
}

class Erzi extends Baba {
    int age = 28;
    public void method(){
        System.out.println(age);        //28
        System.out.println(super.age);  //18
    }
}

第一行sout的代码结果为28,因为采取了就近原则,第二行代码的结果是18,因为我们加入了super,调用父类的成员方法age。

我们之前学过的this关键字:调用本类方法;super是调用父类方法

public class inheritDemo2 {
    public static void main(String[] args) {
        Erzi e = new Erzi();
        e.method();
    }
}

class Baba {
    int age = 18;
}

class Erzi extends Baba {
    int age = 28;
    public void method(){
        int age =38;
        System.out.println(age);        //38
        System.out.println(this.age);   //28
        System.out.println(super.age);  //18
    }
}

在这段代码中,第一个age打印为38是因为就近原则,第二个打印为28是因为调用了本类Erzi中的成员方法age,第三个调用了父类Baba中的成员方法age。


成员方法访问特点

public class inheritDemo2 {
    public static void main(String[] args) {
        Erzi e = new Erzi();
        e.show();
    }
}

class Baba {
    public void show() {
        System.out.println("我是爸爸");
    }
}

class Erzi extends Baba {
    public void show(){
        System.out.println("我是儿子");
    }
}

这段代码打印的是子类方法中的语句,“我是儿子”。

子父类中,出现了方法声明一模一样的方法(方法名,参数,返回值)

在创建子类对象,调用方法的时候,会优先使用子类的方法逻辑

这虽然是就近原则的现象,但其实是子类的方法,对父类的方法,进行了重写操作

方法重写

我们之前学过的方法重载overload与重写Override可以对比记忆

方法重载(Overload):在同一个类中,方法名相同,参数不同,与返回值无关
参数不同:类型不同,个数不同,顺序不同
方法重写(Override):在子父类当中出现了方法声明一模一样的方法(方法名,参数,返回值)

public class inheritDemo2 {
    public static void main(String[] args) {
        Erzi e = new Erzi();
        e.show();
    }
}

class Baba {
    public void show() {
        System.out.println("我是爸爸");
    }
}

class Erzi extends Baba {
    public void show(int num){
        System.out.println("我是儿子");
    }
}

这段代码中打印的就是“我是爸爸”,调用了父类的方法,因为Erzi继承了Baba中的成员方法,所以两个show方法是在同一个类Erzi中,其中两个show方法为重载Overload关系,方法名相同但是参数不同。


那么如何区别子类的方法是重写还是重载,可以在子类方法的上面加注解@Override,如果没报错就是重写了父类的方法;

class Baba {
    public void show() {
        System.out.println("我是爸爸");
    }
}


class Erzi extends Baba {
    @Override
    public void show(){
        System.out.println("我是儿子");
    }
}

适用场景

那么什么时候适用方法重写呢?
当子类需要父类的方法,但是觉得父类的方法逻辑不好(想做修改或增强)就可以对父类的方法进行重写!

public class inheritDemo2 {
    public static void main(String[] args) {
        Erzi e = new Erzi();
        e.play();
    }
}

class Baba {
    public void play() {
        System.out.println("看报纸");
        System.out.println("听收音机");
        System.out.println("下象棋");
    }
}


class Erzi extends Baba {
    @Override
    public void play() {
        super.play();
        System.out.println("刷抖音");
    }
}
//看报纸
//听收音机
//下象棋
//刷抖音

比如这段代码中,儿子想继承爸爸的三个娱乐方式,又想添加自己的娱乐方式,可以使用重写方法,除了打印super.play中父亲的方法,还可以增加自己的内容!

 注意事项

  1. 子类不能调用父类的私有成员方法
  2. 子类重写父类方法的时候,访问权限必须大于等于父类的方法

权限修饰符protected

 在不同的软件包中分别建立两个java文件,Faker和Bin

package com.yuhan.a;

public class Faker {
    protected void show(){
        System.out.println("Faker-vs-Bin");
    }
}
package com.yuhan.b;

import com.yuhan.a.Faker;

public class Bin extends Faker {
    public static void main(String[] args) {
        Bin bin = new Bin();
        bin.show();
    }
}

可以打印出来语句,但是可以看出protected很不方便,权限最多只限于子类的大括号中,我们正常使用的权限修饰符还是private私有和public两种 


特点

Java只支持单继承,不支持多继承,但支持多层继承

 

public class inheritDemo3 {
    public static void main(String[] args) {
        C c = new C();
        c.methodC();
    }
}
class A{
    public void methodA(){
        System.out.println("A.methodA");
    }
}
class B extends A{
    public void methodB(){
        System.out.println("B.methodB");
    }
}
class C extends B{
    public void methodC(){
        methodA();
        methodB();
        System.out.println("C.methodC");
    }
}

C中可以继承B以及B的父类A中的方法


构造方法特点

在所有构造方法的第一行代码,都默认隐藏了一句话 super()通过这句代码,访问父类的空参数构造方法 

public class inheritDemo3 {
    public static void main(String[] args) {
        C c = new C();
    }
}
class A{
    public A(){
        System.out.println("A构造了");
    }
}
class B extends A{
    public B(){
        System.out.println("B构造了");
    }
}
class C extends B{
    public C(){
        System.out.println("C构造了");
    }
}

最终三个语句都会被依次打印,因为真正的代码是这样的:

class A{
    public A(){
        super();
        System.out.println("A构造了");
    }
}
class B extends A{
    public B(){
        super();
        System.out.println("B构造了");
    }
}
class C extends B{
    public C(){
        super();
        System.out.println("C构造了");
    }
}

C调用了B父类的空参数构造方法,B调用了A父类的空参数构造方法


上面的A类已经是“没有父类”了,super()为什么不报错呢,是因为

Java当中所有的类,都直接或者间接的继承到了Object类


案例

可以看见老师和学生有共同的两个成员变量,可以考虑提取出来人类Human这个父类,减少代码

package com.yuhan.test;

public class testDemo1 {
    public static void main(String[] args) {
        Teacher teacher = new Teacher("张三", 30);
        teacher.teach();
        Student student = new Student("李四", 20, 100);
        student.study();
    }
}

class Human {
    private String name;
    private int age;


    public Human() {
    }

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

}

class Teacher extends Human {

    public Teacher() {
        super();
    }

    public Teacher(String name, int age) {
        super(name, age);
    }

    public void teach() {
        System.out.println("姓名为" + super.getName() + ",年龄为" + super.getAge() + "岁的老师正在讲课");
    }
}

class Student extends Human {
    private double score;

    public Student() {
        super();
    }

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public void study() {
        System.out.println("姓名为" + super.getName() + ",年龄为" + super.getAge() + "岁,成绩为" + score + "的学生,正在学习");
    }
}

在Teacher和Student两个类中,带参数的构造函数第一句都是利用父类的构造函数对父类的两个变量进行赋值,由于这两个变量都是两个类共同需要用的,所以两个类都可以使用父类中的getter方法对已经复制的父类成员变量进行输出。

子类中构造方法除了对父类的成员变量进行赋值等操作外,例如Student类,可以对其他参数进行自己的处理。

内存图

假如说我有子类Stutend和父类Person

在Student进行方法构造的时候,堆内存中除了this本类和本类的变量score还会继承父类的成员变量,但是不能直接访问(需要getter和setter简介访问)


综合案例

案例1

程序员和项目经理两个类向上继承到员工类Employee

package com.yuhan.comprehensiveCase1;

public class Test1 {
    public static void main(String[] args) {
        Coder coder = new Coder("张三", 23, 15000);
        coder.work();

        Manager manager = new Manager("李四", 24, 18000, 5000);
        manager.work();
    }
}

class Employee {
    private String name;
    private int age;
    private double salary;

    public void work() {
        System.out.print("姓名为" + name + ",年龄为" + age + ",工资为" + salary);
    }

    public Employee() {
    }

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     *
     * @return salary
     */
    public double getSalary() {
        return salary;
    }

    /**
     * 设置
     *
     * @param salary
     */
    public void setSalary(double salary) {
        this.salary = salary;
    }
}

class Coder extends Employee {
    @Override
    public void work() {
        super.work();
        System.out.println("的程序员正在编写代码");
    }

    public Coder() {
        super();
    }

    public Coder(String name, int age, double salary) {
        super(name, age, salary);
    }
}

class Manager extends Employee {
    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    private double bonus;

    @Override
    public void work() {
        super.work();
        System.out.print(",奖金为" + getBonus() + "的项目经理正在分配任务...");
    }

    public Manager() {
        super();
    }

    public Manager(String name, int age, double salary, double bonus) {
        super(name, age, salary);
        this.bonus = bonus;
    }
}

主要学会私有变量的get和set,继承的构造方法访问特点,父类的work里面可以随便写,反正子类中可以进行方法重写,调用父类的成员变量就需要用super.age等等


super的省略规则

父类的变量或者方法在子类中不存在,子类调用的时候可以省略super

package com.yuhan.inherit;

public class inhetitDemo4 {
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
    }
}

class Fu{
    int num=10;
    public void show(){
        System.out.println("我是父类");
    }
}
class Zi extends Fu{
    public void method(){
        System.out.println(num);
        show();
    }
}
//10
//我是父类

 

学习视频链接

进阶篇-Day1-04-继承介绍和使用_哔哩哔哩_bilibili进阶篇-Day1-04-继承介绍和使用是黑马程序员Java视频教程,一套超哇塞的Java教程,java零基础自学入门必看黑马java教程的第104集视频,该合集共计200集,视频收藏或关注UP主,及时了解更多相关视频内容。https://www.bilibili.com/video/BV1Fv4y1q7ZH?spm_id_from=333.788.player.switch&vd_source=63033bb5836fb27b56e8857a2fbccd65&p=104

相关文章:

  • Ubuntu搭建RTSP服务器
  • DeepSeek学术指南:利用DeepSeek撰写学术论文和需要注意的问题
  • Git 中 rebase, squash, amend 的作⽤
  • 服务器配置-从0到分析2:服务器基本设置
  • 第4章 信息系统架构(四)
  • Git企业开发
  • 机器学习笔记——常用损失函数
  • python 神经网络教程,神经网络模型代码python,小白入门基础教程
  • 云端SaaS系统架构设计
  • Web入侵实战分析-常见web攻击类应急处置实验2
  • 【随手笔记】NB和4G信号杂记
  • golang--字符串处理(rune类型)
  • Qt开源项目获取
  • 【GORM学习笔记】GORM介绍以及增删改查相关操作
  • 算法的解题模式Ⅳ
  • Jenkins 配置 Credentials 凭证
  • vue自定义指令clickOutside篇、元素外部点击事件
  • 拼多多面试题记录
  • JavaScript 中 多个 Promise 嵌套中,如何保证正确的执行顺序?
  • Python学习心得面向对象的三大特征
  • 企业网站建设意义/搜索引擎营销策略有哪些
  • 自助云商城/seo技术培训山东
  • 网站设计论文分类号/河南网站开发公司
  • 提供网站建设课程报告/网站排名优化快速
  • 大连手机自适应网站建设公司/网络营销师报名入口
  • 做创业项目的网站/百度应用商店官网