Java继承详解

这篇具有很好参考价值的文章主要介绍了Java继承详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

继承

为什么需要继承

继承的概念

继承的语法

父类成员的访问

子类中访问父类的成员变量

1.子类和父类不存在同名的成员变量

2.子类和父类成员变量同名

子类中访问父类的成员方法

1.成员方法名字不同

2.成员方法名字相同

super关键字

子类构造方法

super和this

再谈初始化

protected关键字

继承方式

final关键字

继承与组合


继承

为什么需要继承

Java中使用类对现实世界中实体进行描述,类经过实例化之后的产物对象,则可以用来表示现实世界的实体,但是现实世界错综复杂,事物之间可能有一些关联,那再设计程序时就需要考虑。

比如:狗和猫,他们都是动物。(每个动物都有共性,可以抽取出来它们的共性)

使用java语言对狗和猫进行描述,设计出:

//创建一个狗类
public class Dog {
    String name;
    int age;
    float weight;

    public void eat(){
        System.out.println(name + "正在吃饭");
    }

    public void sleep(){
        System.out.println(name + "正在睡觉");
    }

    void bark(){
        System.out.println(name + "汪汪汪");
    }
}


//创建一个猫类
public class Cat {
    String name;
    int age;
    float weight;

    public void eat(){
        System.out.println(name + "正在吃饭");
    }

    public void sleep(){
        System.out.println(name + "正在睡觉");
    }

    void mew(){
        System.out.println(name + "喵喵喵~~~");
    }
}

通过狗类和猫类,我们发现大量代码出现重复,如图所示:

Java继承详解,java,开发语言

那如何能实现共性抽取呢?面向对象的思想中提出了继承的概念,专门用来进行共性抽取,实现代码复用。 (继承可以看作is-a关系,比如Dog is a animal)

继承的概念

继承(inheritance)机制:是面向对象程序设计使代码可以复用的重要手段,它允许程序员在保持原有类的个性的基础上进行扩展,增加新功能,这样产生的新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。继承解决的主要问题是:共性抽取,实现代码复用

例如:狗和猫都是动物,那么我们就可以将共性进行抽取,然后采用继承的思想来达到共用。

Java继承详解,java,开发语言

上述图示中,Dog和Cat都继承了Animal类,其中:Animal类称为父类/基类/超类,Dog和Cat可以称为Animal的子类/派生类,继承之后,子类可以复用父类中的成员,子类在实现时只需关心自己新增加的成员即可。

从继承概念中可以看出继承的最大作用是:实现代码复用,后面也应用于多态

继承的语法

在java中如果要表示类的继承,需要用到extends关键字,具体如下:

修饰符 class 子类名称 extends 父类名称 {
    //...
}

对之前的Dog类和Cat类通过继承重新设计:

//Animal.java
public class Animal {
    String name;
    int age;

    public void eat(){
        System.out.println(name + "正在吃饭");
    }

    public void sleep(){
        System.out.println(name + "正在睡觉");
    }
}

//Dog.java
public class Dog extends Animal {
    void bark() {
        System.out.println(name + "汪汪汪");    
    }
}

//Cat.java
public class Cat extends Animal {
    void mew() {
        System.out.println(name + "喵喵喵");    
    }
}

public class TestExtend {
    public static void main(String[] args) {
        Dog dog = new Dog();
        //dog类中并没有定义任何成员变量,name和age属性肯定是从父类Animal中继承下来的
        System.out.println(dog.name);
        System.out.println(dog.age);
        
        //dog访问的eat和sleep方法也是从Animal中继承下来的
        dog.eat();
        dog.sleep();
        //bark是子类新增加的方法
        dog.bark();
    }
}

注意:

1.子类会将父类中的成员变量或者成员方法继承到子类中了

2.子类继承父类后,建议添加自己特有的成员,体现出与基类的不同,否则没有继承的必要

父类成员的访问

在继承体系中,子类将父类中的方法和字段继承下来了,那在子类中能否直接访问父类中继承下来的成员呢?

子类中访问父类的成员变量

1.子类和父类不存在同名的成员变量
class Base {
    int a;
    int b;
}

public class Derived extends Base {
    int c;
    public void method() {
        a = 10;//访问从父类继承下来的a
        b = 20;//访问从父类继承下来的b
        c = 30;//访问子类自己的c
    }
}
2.子类和父类成员变量同名
class Base {
    int a;
    int b;
    int c;
}

public class Derived extends Base {
    int a;//与父类中成员a同名,而且类型相同
    char b;//与父类中成员b同名,而且类型不同
    public void method() {
        a = 100;//使用的是子类新增的a
        b = 101;//使用的是子类新增的b
        c = 102;//使用从父类继承下来的c
    }
}

通过上述栗子,我们可以得出以下规律:

1.如果访问的成员变量子类中有,则优先访问自己的成员变量

2.如果访问的成员变量子类中没有,则访问从父类继承下来的,如果父类也没有,则报错

3.如果访问的成员变量与父类中的成员变量同名,则优先访问自己的

简:成员变量的访问遵循就近原则,自己有则优先访问自己的,如果没有则在父类中找

子类中访问父类的成员方法

1.成员方法名字不同

总结:成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错

2.成员方法名字相同
class Base {
    public void methodA() {
        System.out.println("Base中的methodA()");
    }

    public void methodB() {
        System.out.println("Base中的methodB()");
    }
}

public class Derived extends Base {
    public void methodA(int a) {
        System.out.println("Derived 中的methodA(int) 方法");
    }

    public void methodB() {
        System.out.println("Derived 中的methodB() 方法");
    }

    public void methodC() {
        methodA();//没有传参,访问父类中的methodA()
        methodA(20);//有传参,访问子类中的methodA(int)
        methodB();//直接访问,则永远访问到的都是子类中的methodB(),永远无法访问到基类的
    }

    public static void main(String[] args) {
        Derived d = new Derived();
        d.methodC();
    }
}

 Java继承详解,java,开发语言

 

总结:通过派生类对象访问父类与子类相同名的方法时,如果父类和子类同名方法的参数列表不同,根据调用方法时传递的参数选择合适的方法进行访问,如果没有则报错。

那么有的人会问,如果成员的访问遵循就近原则,那么如果想访问父类中同名的成员应该怎么办?

这就需要super关键字

super关键字

使用场景:子类和父类中可能存在相同名称的成员,需要在子类方法中访问与父类同名的成员,这时就需要super,该关键字的主要作用:在子类中访问父类的成员

class Parent {
    int value = 10;
    public void methodA() {
        System.out.println("Parent中的methodA()");
    }
}

class Child extends Parent {
    int value = 20;
    public void methodA() {
        System.out.println("Child中的methodA()");
    }
    void printValues() {
        System.out.println("Child value: " + value);         // 子类字段
        System.out.println("Parent value: " + super.value); // 父类字段
        methodA();//子类方法
        super.methodA();//父类方法
    }

    public static void main(String[] args) {
        Child c = new Child();
        c.printValues();
    }
}

执行结果:

Java继承详解,java,开发语言

在子类方法中,如果想要明确访问父类中的成员时,借助super关键字即可。

 注意事项:

1.只能在非静态的方法中使用

2.在子类方法中,调用父类的成员变量和方法

子类构造方法

父子父子,先有父再有子,即:子类对象构造时,需要先调用基类构造犯法,然后执行子类的构造方法。

class Base {
    public Base() {
        System.out.println("Base()");
    }
}
public class Derived extends Base {
    public Derived() {
        //super();//注意子类构造方法中默认会调用基类的无参构造方法:super();
        //用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中的第一条语句
        //并且只出现一次
        System.out.println("Derived()");
    }

    public static void main(String[] args) {
        Derived d = new Derived();
    }
}

执行结果:

Java继承详解,java,开发语言

在子类构造方法中,并没有写任何关于基类构造的代码,但是在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法,因为:子类对象中成员是由两部分组成的,基类继承下来的以及子类新增加的部分。父子父子必是先有父后有子,所以在构建子类对象的时候,先要调用基类的构造方法将从基类继承下来的成员构造完整,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整。 

注意:

1.若父类显式定义无参或者默认的构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类的构造方法

2.如果父类构造方法是带有参数的,此时需要用户为子类显式定义的构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败

3.在子类的构造方法中,super(..)调用父类构造时,必须是子类构造方法中的第一条语句

4.super(...)只能在子类构造中出现一次,并且不能和this同时出现

super和this

super和this都可以在成员方法中用来访问:成员变量和调用其他成员方法,都可以作为构造方法的第一条语句,那它们之间有什么区别呢?

相同点:

1.都是Java的关键字

2.只能在类的非静态方法中使用,用来访问非静态成员方法和字段

3.在构造方法中使用时,必须是构造方法中的第一条语句,并且不能同时存在

不同点:

1.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来的部分成员的引用

2.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类的方法与属性

3.在构造方法中:this(...)用来调用本类的构造方法,super(...)用来调用父类的构造方法,两种调用不能同时在构造方法中出现

4.构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,而this(..)不写则没有

再谈初始化

还记得之前讲过的代码块吗?我们来简要回顾一下几个重要的代码块:实例代码块和静态代码块。

我们之前讲过在没有继承关系下的执行顺序。

1.静态代码块先执行,并且只执行一次,在类的加载阶段执行

2.当有对象创建时,才会执行实例代码块,实例代码块执行完成后,构造方法执行

那么如果现在有继承关系,那它们的执行顺序又是什么?让我们看看下面的代码:

class Person {
    public String name;
    public int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person:构造方法执行");
    }

    {
        System.out.println("Person:实例代码块执行");
    }

    static {
        System.out.println("Person:静态代码块执行");
    }
}

public class Student extends Person {

    public Student(String name, int age) {
        super(name, age);
        System.out.println("Student:构造方法执行");
    }

    {
        System.out.println("Student:实例代码块执行");
    }

    static {
        System.out.println("Student:静态代码块执行");
    }
}

public class Test1 {
    public static void main(String[] args) {
        Student s1 = new Student("zhangsan",19);
        System.out.println("-----------------------------");
        Student s2 = new Student("lisi",22);
    }
}

执行结果:

Java继承详解,java,开发语言

通过分析结果,得出以下结论:

1.父类静态代码块优先于子类静态代码块执行,而且是最早执行

2.父类实例代码块和父类构造方法紧接着执行

3.子类实例代码块和子类构造方法紧接着执行

4.第二次实例化子类对象时,父类盒子类的静态代码块都将不会执行 

protected关键字

  1. 成员可见性: 使用 protected 关键字修饰的成员(字段或方法)可以被同一个包内的其他类访问,以及继承自该类的子类访问。

  2. 访问权限范围: protected 修饰的成员在同一个包内是可见的,同时也对继承关系中的子类可见,即使子类位于不同的包内。

  3. 使用举例:

    package com.example; // 包名
    
    public class Parent {
        protected int value;
        
        protected void printValue() {
            System.out.println("Value: " + value);
        }
    }
    
    
    package com.example; // 同一个包
    
    public class Child extends Parent {
        void accessParent() {
            value = 10;         // 访问父类字段
            printValue();       // 调用父类方法
        }
    }
    
    
    package otherpackage; // 不同包
    
    import com.example.Parent;
    
    public class OtherChild extends Parent {
        void accessParent() {
            value = 20;         // 访问父类字段
            printValue();       // 调用父类方法
        }
    }
    

继承方式

在Java中有以下几种继承方式:

Java继承详解,java,开发语言

注意:java不支持多继承

我们写的类是现实事物的抽象,而我们真正在公司中所遇到的项目往往业务比较复杂,也会涉及到一系列复杂的概念,都需要我们用代码表示,所以在实际项目中写的类比较多,类之间的关系也十分复杂 

但是即使如此,我们并不希望类之间的继承层次太复杂,一般我们不希望超出三层的继承关系,如果继承层数过多,就考虑对代码进行重构了。

如果想从语法上限制继承,就可以使用final关键字

final关键字

final关键字可以用来修饰变量,成员方法和类。

1.修饰变量和字段,表示常量(即不能修改)

final int a = 10;

a = 20;//编译出错

2.修饰类,表示此类不能被继承

final public class Animal {

...

}

public class Bird extends Animal {

...

}

//编译出错

我们平时用的String字符串类,就是用final修饰的,不能被继承

3.修饰方法:表示该方法不能被重写(后面介绍)

继承与组合

和继承类似,组合也是一种表达类之间关系的方式,也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如extends关键字),仅仅是将一个类的实例作为另一个类的字段

继承表示对象之间是is-a的关系,比如:狗是动物,猫是动物。

组合表示对象之间是has-a的关系,比如:汽车有轮胎,汽车有发动机。

举个例子:汽车和其轮胎,发动机,方向盘,车载系统等的关系就应该是组合,因为汽车是由这些部件组成的。

//轮胎类
class Tire {
    //...
}

//发动机类
class Engine {
    //...
}

//车载系统类
class VehicleSystem {
    //...
}

class Car {
    private Tire tire;//可以复用轮胎中的属性和方法
    private Engine engine;//可以复用发动机中的属性和方法
    private VehicleSystem vs;//可以复用车载系统类中的属性和方法
    //。。。
}
public class Benz extends Car {
    //将汽车中的轮胎,发动机,车载系统全部继承下来
}

组合和继承都可以实现代码的复用,应该使用继承还是组合,需要根据应用场景来选择。一般建议:能用组合尽量用组合文章来源地址https://www.toymoban.com/news/detail-649383.html

到了这里,关于Java继承详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java 基础】引用型数组、Java 继承、super 关键字详解

    《 Java 零基础入门到精通 》 专栏持续更新中。通过本专栏你将学习到 Java 从 入门 到 进阶 再到 实战 的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。 订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java

    2024年02月03日
    浏览(38)
  • 【我与Java的成长记】之继承详解(二)

    能看懂文字就能明白系列 C语言笔记传送门 Java笔记传送门 🌟 个人主页 :古德猫宁- 补充上篇笔记的知识点 在上篇文章中,我们最后讲到了子类访问父类中的成员可能会遇到的两种情况,一种是子类的成员名称和父类的名称不相同,另一种则是子类的成员名称和父类相同。

    2024年02月01日
    浏览(27)
  • 编程开发8大语言详解,为什么Java是我最推荐的?

    很多没有接触过编程语言的同学,都会觉得编程开发特别高端和神奇,担心理解不了更担心学不会。 当然,也有人会认为,你既然是做编程的,那么你应该什么都会,什么软件的开发都能完成,这是平哥经常听到的两种声音。 在此,平哥需要给大家科普一下, 编程确实改变

    2024年02月05日
    浏览(53)
  • Java SE 继承和多态 (图文搭配,万字详解!!)

    目录 1.继承 1.1 为什么需要继承 1.2 继承概念  1.3 继承的语法 1.4 父类成员访问 1.4.1 子类中访问父类的成员变量 1.4.2 子类中访问父类的成员方法  1.5 super  1.6 子类构造方法 1.7 super和this 1.8 再谈初始化 1.9 protected 1.10 继承方式  1.11 final 1.12 继承与组合 2

    2024年02月05日
    浏览(41)
  • c、c++、java、python、js对比【面向对象、过程;解释、编译语言;封装、继承、多态】

    目录 内存管理、适用 区别 C 手动内存管理:C语言没有内置的安全检查机制,容易出现内存泄漏、缓冲区溢出等安全问题。 适用于系统级编程 C++ 手动内存管理:C++需要程序员手动管理内存,包括分配和释放内存,这可能导致内存泄漏和指针错误。 适用于游戏引擎和系统级编

    2024年02月08日
    浏览(64)
  • 开发语言漫谈-Java

            由于C++过于复杂,Java诞生了。与C++相比,Java更易于学习和使用,它去掉C++中的指针和解决了内存管理问题。Java提供了垃圾自动回收机制,自动管理不再使用的内存。Python又进一步简化,使得语法更简洁,更易于阅读和编写。当然随着简化,性能就越来越低。    

    2024年04月10日
    浏览(36)
  • JAVA开发(Spring框架详解)

    javaweb项目几乎已经离不开spring框架了,spring 是一个典型的分层架构框架,它包含一系列的功能并被分为多个功能模块,springboot对spring框架又做了一层封装,以至于很多人对原来的spring框架越来越不了解。         要谈Spring的历史,就要先谈J2EE。J2EE应用程序的广泛实现是

    2023年04月20日
    浏览(31)
  • 「Java」《Java集合框架详解:掌握常用集合类,提升开发效率》

    Java 集合框架是 Java 编程中不可或缺的一部分。它提供了一组强大的数据结构和算法,用于存储、操作和处理对象数据。本文将深入探讨 Java 集合框架的核心概念,介绍常用的集合接口和实现类,并提供实际应用示例,帮助读者更好地理解和应用集合框架,提升开发效率。

    2024年02月11日
    浏览(36)
  • Java语言:字符型的详解、字符串的比较

    目录 前言 一.字符型的知识 二.字符型比较大小 三.字符串比较 equals()方法 equalslgnoreCase()方法 compareTo() 方法 🎁博主介绍:博客名为tq02,已学C语言、JavaSE,目前学了MySQL和JavaWeb 🎥学习专栏:  C语言         JavaSE       MySQL基础 🎄博主链接:tq02的博客_CSDN博客-C语言,Ja

    2024年02月13日
    浏览(38)
  • 【Java】还不理解继承?一篇文章看懂继承|继承入门

    作者: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:算法、数据结构、Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: Java岛冒险记【从小白到大佬之路】;该专栏专注于Java相关知识,持续更新,每一篇内容优质,浅显易懂,不失深度!

    2024年02月01日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包