Java中面对对象三大特征 继承

本文深入讲解Java中的继承机制,包括继承的基本概念、语法、父类成员的访问方式、super关键字和方法覆盖等内容,并通过具体示例说明继承的优点及代码执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

继承

举个简单的例子《西虹市首富》中的王多鱼从他的二爷那里继承的财产这就叫继承而在Java中的继承又是怎样的呢?

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

继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字

class 父类{
    ...       //成员变量、成员方法
}
class 子类 extends 父类{
    ...       //类体
}
public class Father {
    public String name;
    public int age;
    public String gender;
    public void show(){
        System.out.println("姓名:"+name);
        System.out.println("年龄:"+age);
        System.out.println("性别:"+gender);
    }
}
class Son extends Father{

}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
        son.name="张三";
        son.age=11;
        son.gender="男";
        son.show();
    }
}

在这里插入图片描述

此时我们并没有在Son类中给任何成员变量和方法,却可以通过实例化对象Son来访问Father类中的成员变量和方法,这里Son就是继承了Father中的成员变量和方法

父类成员的访问

当成员变量和成员方法不同名的时候

public class Father {
    public String name="杰瑞";
    public int age=41;
    public String gender="男";
    public void sayhello(){
        System.out.println("大家好!我是父亲杰瑞");
    }
}
class Son extends Father{
    public void saybye(){
        System.out.println("再见!");
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
        son.sayhello();
        son.saybye();
        System.out.println("姓名:"+son.name+" 年龄:"+son.age+" 性别:"+son.gender);
    }
}

在这里插入图片描述

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

当成员变量和成员方法同名的时候

public class Father {
    public String name="杰瑞";
    public int age=41;
    public String gender="男";
    public void sayhello(){
        System.out.println("大家好!我是父亲杰瑞");
    }
    public void saybye(){
        System.out.println("再见!");
    }
}
class Son extends Father{
    public String name="莫迪";
    public int age=12;
    public void sayhello(){
        System.out.println("大家好!我是儿子莫迪");
    }
    public void show(){
        System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
        son.sayhello();
        son.saybye();
        son.show();
    }
}

在这里插入图片描述

在子类方法中 或者 通过子类对象访问成员时: 如果访问的成员变量子类中有,优先访问自己的成员变量。
如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
如果访问的成员变量与父类中成员变量同名,则优先访问自己的
成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

super关键字和函数的覆盖

在继承关系中,子类会自动继承父类中定义的方法,但有时在子类中需要对继承的方法进行一些修改,即对父类的方法进行重写。需要注意的是,在子类中重写的方法需要和父类被重写的方法具有相同的方法名、参数列表以及返回值类型当子类重写父类的方法后,子类对象将无法访问父类被重写的方法,为了解决这个问题,在Java中专门提供了一个super关键字用于访问父类的成员

public class Father {
    public String name="杰瑞";
    public int age=41;
    public String gender="男";
    public void sayhello(){
        System.out.println("大家好!我是父亲杰瑞");
    }
    public void saybye(){
        System.out.println("再见!");
    }
}
class Son extends Father{
    public String name="莫迪";
    public int age=12;
    public void sayhello(){
        System.out.println("大家好!我是儿子莫迪");
    }
    public void show(){
        super.sayhello();
        System.out.println("姓名:"+super.name+" 年龄:"+super.age+" 性别:"+gender);
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
        son.sayhello();
        son.saybye();
        son.show();
    }
}

在这里插入图片描述
此时成员方法同名的时候我们通过super关键字就可以访问到父类成员的方法和变量了

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类中的方法,这样,即沿袭了父类的功能,又定义了子类特有的内容,这就是覆盖

public class Father {
    public String name="杰瑞";
    public int age=41;
    public String gender="男";
    public void sayhello(){
        System.out.println("大家好!我是父亲杰瑞");
    }
    public void saybye(){
        System.out.println("再见!");
    }
}
class Son extends Father{
    public String name="莫迪";
    public int age=12;
    public void sayhello(){
        System.out.println("大家好!我是儿子莫迪");
    }
    public void show(){
        System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
        son.sayhello();
        son.show();
    }
}

在这里插入图片描述
这里就重写了name,age,sayhello成员变量和方法同时沿用了父类gender的属性

子类构造方法

public class Father {
    public Father(){
        System.out.println("大家好!我是父亲杰瑞");
    }
}
class Son extends Father{
    public Son (){
        System.out.println("大家好!我是儿子莫迪");
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
    }
}

在这里插入图片描述

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

注意:

  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(…)用户不写则没有

final关键字

final关键字可用于修饰类、变量和方法,它有“无法改变”或者“最终”的含义,因此被final修饰的类、变量和方法将具有以下特性:
final可以修饰类,方法,变量 final修饰的类不可以被继承 final修饰的方法不可以被覆盖
final修饰的变量是一个常量,只能被赋值一次

为什么要用final修饰变量,其实,在程序中如果一个数据是固定的。那么直接使用这个数据就可以了,但是这种阅读性差,所以应该给数据起个名称。而且这个变量名称的值不能变化,所以加上final固定

public final class Father {
    public Father(){
        System.out.println("大家好!我是父亲杰瑞");
    }
}
class Son extends Father{
    public Son (){
        System.out.println("大家好!我是儿子莫迪");
    }
}
class Family{
    public static void main(String[] args) {
        Son son=new Son();
    }
}

在这里插入图片描述
此时被final关键字修饰的类是无法被继承的

public class Number {
    public static void main(String[] args) {
        final int a = 10;
         a=20;
        System.out.println(a);
    }
}

在这里插入图片描述
被final修饰的常量是无法修改的

继承的优点

继承过来的字段和方法,可以像任何其他字段和方法一样被直接使用;
在子类中可以声明一个与父类中同名的新字段或静态方法,从而“隐藏”父类中的字段或方法; 可以在子类中声明一个在父类中没有的新字段和方法;
可以在子类中编写一个父类当中具有相同名的新实例方法,这称为“方法重写”或“方法覆盖”;
可以在子类中编写一个调用父类构造方法的子类构造方法,既可以隐式地实现,也可以通过使用关键字super来实现

代码执行顺序

父类静态代码块 > 子类静态代码块 > main()方法 > 父类代码块 > 父类构造方法 > 子类代码块 > 子类构造方法

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值