Java由浅入深刨析继承

目录
  • 继承
    • 继承的介绍
    • 生活中的继承
    • 继承的好处
    • 继承的格式
    • 继承的demo
    • 子类不能继承的内容
    • super与this关键字
    • 构造器不能被继承
    • final修饰的类不能被继承
  • 方法重写
    • 介绍
    • 使用场景与案例
    • @Override重写注解
    • 注意事项
  • 完结

茫茫人海千千万万,感谢这一秒你看到这里。希望我的面试题系列能对你的有所帮助!共勉!

愿你在未来的日子,保持热爱,奔赴山海!

Java基础知识(继承)

继承

继承的介绍

继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。描述的是事物之间的所属关系,这种关系是:is-a 的关系。

继承:就是子类继承父类的属性和行为,使得子类对象(实例)可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

生活中的继承

兔子和长颈鹿属于食草动物类,老虎和狮子属于食肉动物类。而食草动物和食肉动物又是属于动物类。

那是不是兔子、长颈鹿、老虎、狮子都属于动物类呢?答案是没错滴!虽然食草动物和食肉动物都是属于动物,但是两者的属性和行为上有差别,所以子类会具有父类的一般特性也会具有自身的特性。我们就可以再多个类中存在相同属性和行为时,我们可以将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。

继承的好处

  • 提高代码的复用性(减少代码冗余,相同代码重复利用)。
  • 使类与类之间产生了关系。
  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。

继承的格式

在Java当中会通过extends关键字可以申明一个类是从另外一个类继承而来的,一般形式如下:

class 父类 {
}

class 子类 extends 父类 {
}

需要注意一点: Java 不支持多继承,但支持多重继承。就如下:

class A {
}

class B extends A { (对的)
}

class C extends A, B { (错的)
}

class C extends B { (对的)
}

顶层父类是Object类。所有的类默认继承Object,作为父类。

继承的demo

编写一个父类极其对应的子类信息

结构如下:

代码如下:

父类Person:

package com.nz.pojo;

public class Person {
    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;
    }
}

子类Student没有额外的属性和方法:

package com.nz.pojo;

/**
 * 继承了Person特有的name, age,
 * 没有额外的独有属性和方法
 */
public class Student extends Person{
}

子类Teacher多了一个工资的属性和独有的教书方法:

package com.nz.pojo;

/**
 * 继承了Person特有的name, age,
 * 多了自己独有的工资属性还有独有的教书方法
 */
public class Teacher extends Person{

    // 工资
    private double salary ;

    // 特有方法
    public void teach(){
        System.out.println("老师在认真教书!");
    }

    public double getSalary() {
        return salary;
    }

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

编写测试代码:

package com.nz;

import com.nz.pojo.Student;
import com.nz.pojo.Teacher;

public class InheritDemo {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        teacher.setName("最爱吃鱼罐头");
        teacher.setAge(18);
        teacher.setSalary(1999.99);
        System.out.println(teacher.getName());
        System.out.println(teacher.getAge());
        System.out.println(teacher.getSalary());
        teacher.teach();

        Student student = new Student();
        student.setName("罐头");
        student.setAge(12);
        //student.setSalary(1999.99); // student没有工资属性,报错!
        System.out.println(student.getName());
        System.out.println(student.getAge());
    }
}

结果如下:

最爱吃鱼罐头
18
1999.99
老师在认真教书!
罐头
12

从结果来看,子类继承父类,就可以直接得到父类的成员变量和方法。而子类可以编写一些特有的属性和方法,但是是否可以继承所有成分呢?

子类不能继承的内容

并不是父类的所有内容都可以给子类继承的:

super 与 this 关键字

这里先将这两个关键字,super和this在继承关系中,运用比较频繁。

  • super关键字:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。
  • this关键字:指向自己本类的引用。

super和this完整的用法如下:

this.成员变量 -- 本类的
super.成员变量 -- 父类的

this.成员方法名() -- 本类的
super.成员方法名() -- 父类的

  • 具体演示,创建测试InheritDemo2:
package com.nz;

public class InheritDemo2 {
    public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();
        Cat cat = new Cat();
        cat.eatFish();
    }
}

class Animal {
    void eat() {
        System.out.println("animal : eat");
    }
}

class Cat extends Animal {
    void eat() {
        System.out.println("cat : eat");
    }
    void eatFish() {
        this.eat();   // this 调用自己的方法
        super.eat();  // super 调用父类方法
    }
}

调用结果如下:

animal : eat
cat : eat
animal : eat

  • 注意:

子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。

super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

构造器不能被继承

  • 子类不能继承父类的构造器(构造方法或者构造函数),它只是调用(隐式或显式)。因为子类有自己的构造器。值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。
  • 如果父类的构造器带有参数,则必须在子类的构造器中显式地通过super 关键字调用父类的构造器并配以适当的参数列表。
  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
  • 演示过程:
package com.nz;

public class InheritDemo3  {
    public static void main(String[] args) {
        System.out.println("------Teacher 类继承------");
        Teacher teacher = new Teacher();
        Teacher teacher2 = new Teacher("张三");
        System.out.println("------Student 类继承------");
        Student student = new Student();
        Student student2 = new Student("张三三");
    }
}
// 父类
class Person {
    private String name;
    Person(){
        System.out.println("调用了父类的无参构造器: Person()");
    }
    Person(String name) {
        System.out.println("调用了父类的带参构造器: Person(String name)");
        this.name = name;
    }
}
// Teacher子类继承Person
class Teacher extends Person{
    private String name;
    Teacher(){
        // 自动调用父类的无参数构造器 因为会有默认super();
        System.out.println("Teacher");
    }

    public Teacher(String name){
        super("最爱吃鱼罐头");  // 调用父类中带有参数的构造器
        System.out.println("Teacher(String name):"+name);
        this.name = name;
    }
}
// Student子类继承Person
class Student extends Person{
    private String name;

    Student(){
        super("heihei");  // 调用父类中带有参数的构造器
        System.out.println("SubClass2");
    }

    public Student(String name){ // 自动调用父类的无参数构造器
        System.out.println("Student(String name):"+name);
        this.name = name;
    }
}

结果如下:

------Teacher 类继承------
调用了父类的无参构造器: Person()
Teacher
调用了父类的带参构造器: Person(String name)
Teacher(String name):张三
------Student 类继承------
调用了父类的带参构造器: Person(String name)
SubClass2
调用了父类的无参构造器: Person()
Student(String name):张三三

final修饰的类不能被继承

final 关键字主要用在三个地方:变量、方法、类。

  • 修饰类:表示该类不能被继承;
  • 修饰方法:表示方法不能被重写;
  • 修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

final 的特点:

  • 对于一个 final 变量,如果是基本数据类型的变量,则其数值一旦在初始 化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不 能再让其指向另一个对象。
  • 当用 final 修饰一个类时,表明这个类不能被继承。final 类中的所有成员 方法都会被隐式地指定为 final 方法。
  • 使用 final 方法的原因有两个。第一个原因是把方法锁定,以防任何继承 类修改它的含义;第二个原因是效率。在早期的 Java 实现版本中,会将 final 方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用 带来的任何性能提升(现在的 Java 版本已经不需要使用 final方法进行这些优化了)。类中所有的 private 方法都隐式地指定为 final。

我们测试下修饰类后到底能不能继承:

package com.nz;

public class InheritDemo4 {
}

// 父类
final class Fu {
    private String name;
}

//class Zi extends Fu{ // Cannot inherit from final 'com.nz.Fu' 会显示没办法继承Fu
//}

结果:可以看出来在被final修饰的Fu类没办法继承,而且在编译期间就会报错了,没办法通过运行。

方法重写

介绍

子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。

使用场景与案例

发生在子父类之间的关系。 子类继承了父类的方法,但是子类觉得父类的这方法不足以满足自己的需求,子类重新写了一个与父类同名的方法,以便覆盖父类的该方法。

写个测试案例:

package com.nz;

public class InheritDemo5 {

    public static void main(String[] args) {
        // 创建子类对象
        Cat lanMao = new Cat();
        // 调用父类继承而来的方法
        lanMao.run();
        // 调用子类重写的方法
        lanMao.sing();

    }
}

class Animal{
    public void sing(){
        System.out.println("动物都可以唱歌!");
    }
    public void run(){
        System.out.println("动物都可以跑!");
    }
}

class Cat extends Animal {
    public void sing(){
        System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
    }
}

运行结果:

动物都可以跑!
我们一起学猫叫,一起喵喵喵!让我们一起撒个娇

可以看出,蓝猫调用了重写后的sing方法。

@Override重写注解

  • @Override:注解,重写注解校验!
  • 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
  • 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!

加上后的子类代码形式如下:

class Cat extends Animal {
    // 声明不变,重新实现
    // 方法名称与父类全部一样,只是方法体中的功能重写了!
    @Override
    public void sing(){
        System.out.println("我们一起学猫叫,一起喵喵喵!让我们一起撒个娇");
    }
}

注意事项

  • 方法重写是发生在子父类之间的关系。
  • 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
  • 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。、

完结

相信各位看官看到这里,都对Java继承有了一定的了解吧,继承在Java的特性里还是占据比较大得多作用,他还有很多特点:

  • 高代码的复用性(减少代码冗余,相同代码重复利用)。
  • 使类与类之间产生了关系。
  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展,可以用自己的方式实现父类的方法。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

让我们也一起加油吧!本人不才,如有什么缺漏、错误的地方,也欢迎各位人才大佬评论中批评指正!

学到这里,今天的世界打烊了,晚安!虽然这篇文章完结了,但是我还在,永不完结。我会努力保持写文章。来日方长,何惧车遥马慢!

感谢各位看到这里!愿你韶华不负,青春无悔!

到此这篇关于Java由浅入深刨析继承的文章就介绍到这了,更多相关Java 继承内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈Java封装、继承、多态特性

    目录 1.封装 2.继承 3.多态 4.上代码,效果运行放在最后 1.封装 什么是封装,谈谈自己对封装的理解,封装就是将类的信息(比如说类的属性)隐藏在类的内部,不允许外部程序直接访问.此时就要提到一个关键字private,他是一个权限修饰符,可以用来修饰成员(变量和方法),保护成员不被其他别的类来使用,如果需要被其他类来使用,那么需要提供对应的操作:a.提供get变量名()方法,用于获取成员变量的值 b.提供set变量名(参数),用于设置成员变量的值,同样也和get方法一样,都是用public

  • JAVA面向对象之继承 super入门解析

    目录 1 继承 1.1概念 1.2 特点 1.3 练习:继承入门案例 2 super 3 继承的用法 3.1 练习:super之继承中成员变量使用 3.2 练习:super之继承中构造方法的使用 4 方法重写Override 4.1 练习:继承中成员方法的使用 5 拓展 5.1 继承的好处与坏处 5.2 this与super的区别 5.3 重载Overload与重写Override的区别 1 继承 1.1概念 继承是面向对象最显著的一个特征 继承是从已有的类中派生出新的类,新类能吸收已有类的数据

  • java继承学习之super的用法解析

    继承supersuper关键字的用法和this关键字的用法相似this:代表本类对象的引用super:代表父类存储空间的标识(可以理解为父类对象引用) package com.ithema_20; /*   测试类   继承   super   super关键字的用法和this关键字的用法相似   this:代表本类对象的引用   super:代表父类存储空间的标识(可以理解为父类对象引用)  */ public class Demo {     public static void main(

  • Java中的接口多继承机制

    目录 问题原因 一个接口可以同时继承多个接口 接口不能实现任何接口 一个类可以实现多个接口 一个类只能继承一个父类 总结: 问题原因 今天在看集合源码的时候,突然看到接口继承接口,觉得有点差异,以前写代码也就是类继承一个类,实现接口.这样写的多了,突然看到接口继承接口就有点诧异了,以为哪里不对.就测试,查阅了一些资料 一个接口可以同时继承多个接口 书写接口测试 public interface Jiekou extends Jiekou1,Jiekou2{ void jiekou(); } pu

  • Java继承与多态的正确打开方式

    目录 一.概述 二.继承 2.1 继承的概述 2.2 继承机制 2.3 类中属性,方法的继承与覆盖 1.属性的继承与覆盖 2.方法的继承与覆盖 2.4 super 关键字 三. 多态 总结 一.概述 面向对象程序设计的三大原则是封装性,继承性和多态性.继承性是子类自动共享父类的数据和方法的机制,它是由类的派生功能体现的.继承具有传递性,使得一个类可以继承另一个类的属性和方法,这样通过抽象出共同的属性和方法组件新的类,便于代码的重用.而多态是指不同类型的对象接收相同的消息时产生不同的行为,这里的消

  • 详解Java的继承

    目录 继承: 继承的好处: 继承的坏处: 继承的特点: 继承和成员变量之间的关系: this关键字和super关键字的区别 方法的重写: 总结 继承: 把多个类相同的内容提取到另外一个类中,然后使用关键字extends来实现继承 继承的好处: 1.提高了代码的复用性 2.提高了代码的维护性 只需要修改父类的内容 3.让类与类之间产生了继承关系,为了后面的多态做铺垫,要有继承才能做多态 继承的坏处: 1.类的耦合性增强了,一个父类改变了,子类也跟着改变 2.只可以单个继承,不可以多个继承,可以多层

  • 解析JavaSE的继承和多态

    目录 1.继承 1.子类继承了父类,获得父类的全部Field和方法. 2.子类继承了父类,额外增加新的Field和方法 3.子类继承了父类,重写父类中的方法 4.super限定,在子类调用父类中被覆盖的方法 2.多态 3.引用变量的强制类型转换 4.面试题 1.Java中实现多态的机制是什么? 2.谈谈你对多态的理解? 总结 1. 继承 1. 子类继承了父类,获得父类的全部Field和方法. 子类Student类继承父类,将可以获得父类的全部Field和方法 public class Perso

  • Java面向对象之类的继承介绍

    目录 继承的作用 如果没有继承机制是怎么样的? 使用继承机制后的示例? 类的继承是什么? 子类和父类的继承机制 Java单继承 Java继承的顶级父类:Object 对象的类型转换 对象向上转型 对象向下转型 总结 继承的作用 如果没有继承机制是怎么样的? 有以下两个类,分别是Student.Teacher,它们的实现类如下: /** * 老师类 封装了姓名.年龄 * * @author Administrator * */ public class Teacher { private Stri

  • java面向对象继承与多态介绍

    目录 一.概述 二.继承 2.1 继承的概述 2.2 继承机制 2.3 类中属性,方法的继承与覆盖 2.4 super 关键字 三. 多态 总结 一.概述 面向对象程序设计的三大原则是封装性,继承性和多态性.继承性是子类自动共享父类的数据和方法的机制,它是由类的派生功能体现的.继承具有传递性,使得一个类可以继承另一个类的属性和方法,这样通过抽象出共同的属性和方法组件新的类,便于代码的重用.而多态是指不同类型的对象接收相同的消息时产生不同的行为,这里的消息主要是对类成员函数的调用,而不同的行为是指

  • Java由浅入深刨析继承

    目录 继承 继承的介绍 生活中的继承 继承的好处 继承的格式 继承的demo 子类不能继承的内容 super与this关键字 构造器不能被继承 final修饰的类不能被继承 方法重写 介绍 使用场景与案例 @Override重写注解 注意事项 完结 茫茫人海千千万万,感谢这一秒你看到这里.希望我的面试题系列能对你的有所帮助!共勉! 愿你在未来的日子,保持热爱,奔赴山海! Java基础知识(继承) 继承 继承的介绍 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类.描述的是事

  • Java集合框架之List ArrayList LinkedList使用详解刨析

    目录 1. List 1.1 List 的常见方法 1.2 代码示例 2. ArrayList 2.1 介绍 2.2 ArrayList 的构造方法 2.3 ArrayList 底层数组的大小 3. LinkedList 3.1 介绍 3.2 LinkedList 的构造方法 4. 练习题 5. 扑克牌小游戏 1. List 1.1 List 的常见方法 方法 描述 boolean add(E e) 尾插 e void add(int index, E element) 将 e 插入到 inde

  • Java面向对象特性深入刨析封装

    目录 1.认识封装 2.控制访问权限-访问修饰符 3.理解封装必须要知道-包 3.1理解包的概念 3.2 导入包中的类 3.3 自定义包 3.4 包的访问权限控制 3.5 java中常见的包 前面已经提过了 Java是一门面向对象(oop)的进行编程的语言, 面向对象的编程,有很多的好处,比如更容易开拓思维,分工合作,提高开发效率, 最主要的是 可重用性高,也就是下面将要提到的这三个核心特性(封装,继承,多态). 可扩展性,易于管理. 1.认识封装 简单的一句话就是套壳屏蔽细节. 比如说一部手机

  • Java项目工程代码深度刨析总结

    目录 一.背景 二.衡量代码好环的原则 2.1 评判代码指标 2.2 指导理论 三.代码实现技巧 3.1 抽像能力 3.2 组合/聚合复用原则 四.总结 一.背景   最近我们团队有幸接了两个0到1的项目,一期项目很紧急,团队成员也是加班加点,从开始编码到完成仅用了一星期多一点点,期间还不断反复斟酌代码如何抽象代码,如何写得更优雅,一遍又一遍的调整,我也是一次又次的阅读每个团队成员的代码,虽然还有些不如意,但整体来说还算是满意,参与项目的成员经过不断琢磨,对一些功能不断抽像,团队进步也是非常明显

  • Java 逻辑结构与方法函数详解刨析

    ⭐前言⭐ 本文主要介绍JavaSE的逻辑结构和方法. 对一门编程语言逻辑结构和方法的理解是站在C语言之上的,建议配套C语言版本的分析一起食用 链接直达:

  • Java集合框架之Stack Queue Deque使用详解刨析

    目录 1. Stack 1.1 介绍 1.2 常见方法 2. Queue 2.1 介绍 2.2 常见方法 3. Deque 3.1 介绍 3.2 常见方法 1. Stack 1.1 介绍 Stack 栈是 Vector 的一个子类,它实现了一个标准的后进先出的栈.它的底层是一个数组. 堆栈只定义了默认构造函数,用来创建一个空栈.堆栈除了包括由 Vector 定义的所有方法,也定义了自己的一些方法. 1.2 常见方法 方法 描述 E push(E item) 压栈 E pop() 出栈 E pee

  • Java 关于时间复杂度和空间复杂度的深度刨析

    目录 1.算法效率 2.时间复杂度 2.1时间复杂度的概念 2.2大O的渐进表示法 2.3常见时间复杂度计算 2.3.1常用的时间复杂度量级 2.3.2常见示例举例 2.3.2示例答案及分析 3.空间复杂度 1.算法效率 算法效率分析分为两种:第一种是时间效率,第二种是空间效率.时间效率被称为时间复杂度,而空间效率被称作空间复杂度. 时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间 如今我们更关注的是时间复杂度,而对空间复杂度已不再关注. 2.时间复杂度 2

  • Java 十大排序算法之冒泡排序刨析

    目录 冒泡排序原理 冒泡排序API设计 冒泡排序的代码实现 冒泡排序的时间复杂度分析 冒泡排序原理 ①比较相邻的元素,如果前一个元素比后一个元素大,则交换这两个元素的位置 ②对每一对相邻的元素循环上面的步骤,最终最后面的元素就是最大值 冒泡排序API设计 类名 Bubble 构造方法 Bubble:创建Bubble对象 成员方法 1.public static void sort(Comparable[] a):对数组内元素进行排序 2.private static void greater(C

  • Java 十大排序算法之选择排序刨析

    目录 选择排序原理 选择排序API设计 选择排序代码实现 选择排序的时间复杂度 选择排序原理 ①假设第一个索引处的元素为最小值,和其他值进行比较,如果当前的索引处的元素大于其他某个索引处的值,则假定其他某个索引处的值为最小值,最后找到最小值所在的索引 ②交换第一个索引处和最小值所在的索引处的值 选择排序API设计 类名 Selection 构造方法 Selection():创建Selection对象 成员方法 1.public static void sort(Comparable[] a):对

  • Java 十大排序算法之插入排序刨析

    目录 插入排序原理 插入排序API设计 插入排序代码实现 插入排序的时间复杂度分析 插入排序原理 ①把所有元素分成已排序和未排序两组 ②找到未排序组的第一个元素,向已经排序的组中进行插入 ③倒序遍历已经排好的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他元素向后移动一位 插入排序API设计 类名 Insertion 构造方法 Insertion():创建Insertion对象 成员方法 1.public static void sort

随机推荐