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

java面向对象编程【高级篇】之继承

目录

  • 🚀前言
  • 🤔什么是继承?
  • 🌟权限修饰符
    • 💯private 修饰符
    • 💯默认(无修饰符)
    • 💯protected 修饰符
    • 💯public 修饰符
    • 💯归纳
  • 🦜继承的特点
    • 💯单继承
    • 💯Object类
    • 💯就近原则
  • ✍️方法重写
    • 💯@Override
    • 💯方法重写的注意事项
    • 💯toString方法重写
  • 🐧子类构造器的特点
    • 💯this与super的区别

🚀前言

在这里插入图片描述

大家好!我是 EnigmaCoder
本文主要介绍java面向对象编程中的继承部分,包括定义、权限修饰符、特点、方法重写等。

🤔什么是继承?

在java中,继承是面向对象的三大特性之一,它允许一个类(称为子类或派生类)直接获取另一个类(称为父类或超类或基类)的属性和方法,从而实现代码重用和建立类之间的层次关系。

  • 使用extends关键字完成继承,格式如下:
class A{}                      //父类A
class B extends A{}            //子类B继承父类A
  • 子类能继承父类的非私有成员(成员变量、成员方法)。
  • 子类的对象是由子类和父类共同完成的。

代码案例:

class Person {private String name;private int age;public void setName(String name){this.name=name;}public String getName(){return name;}public void setAge(int age){this.age=age;}public int getAge(){return age;}
}class Student extends Person{
}class Test{public static void main(String[] args){Student stu =new Student();stu.setName("张三");stu.setAge("18");System.out.println("姓名:"+stu.getName()+",年龄:"+stu.getAge());}
}

运行结果:

姓名:张三,年龄:18

可见,通过继承的功能可以直接将父类中的操作拿到子类中使用,即使子类中没有定义任何操作。

当然,子类也可以定义自己的属性和方法,可以通过子类扩展父类的功能,例如:

class Student extends Person{private String school;public void setSchool(String school){this.school=school;}public String getSchool(){return school;} 
}

这样,主方法中也能setSchool()getSchool()方法。

🌟权限修饰符

💯private 修饰符

  • 访问权限:只能在定义它的类内部被访问。
  • 使用场景:常用于隐藏类的内部数据和实现细节,防止外部直接访问和修改,保证数据的安全性和封装性。
  • 示例代码
class PrivateExample {// 私有成员变量private int privateVariable = 10;// 私有方法private void privateMethod() {System.out.println("This is a private method.");}public void accessPrivateMembers() {// 可以在类内部访问私有成员System.out.println(privateVariable);privateMethod();}
}public class Main {public static void main(String[] args) {PrivateExample example = new PrivateExample();// 以下代码会报错,因为不能在类外部访问私有成员// System.out.println(example.privateVariable); // example.privateMethod(); example.accessPrivateMembers();}
}

💯默认(无修饰符)

  • 访问权限:也称为包访问权限,只能被同一个包中的类访问。
  • 使用场景:当你希望某些类、方法或变量仅在同一个包内可见时使用,有助于组织和管理代码,将相关的类放在同一个包中并相互访问。
  • 示例代码
// 假设在 com.example 包下
package com.example;class DefaultExample {// 默认成员变量int defaultVariable = 20;// 默认方法void defaultMethod() {System.out.println("This is a default method.");}
}// 同一个包中的另一个类
class AnotherClassInSamePackage {public static void main(String[] args) {DefaultExample example = new DefaultExample();// 可以在同一个包中访问默认成员System.out.println(example.defaultVariable);example.defaultMethod();}
}

💯protected 修饰符

  • 访问权限:可以被同一个包中的类访问,也可以被不同包中的子类访问。
  • 使用场景:当你希望某个类的成员不仅能在同一个包中被访问,还能被不同包的子类继承和使用时使用。
  • 示例代码
// 假设在 com.parent 包下
package com.parent;public class ParentClass {// 受保护的成员变量protected int protectedVariable = 30;// 受保护的方法protected void protectedMethod() {System.out.println("This is a protected method.");}
}// 假设在 com.child 包下
package com.child;import com.parent.ParentClass;class ChildClass extends ParentClass {public void accessProtectedMembers() {// 可以在不同包的子类中访问受保护成员System.out.println(protectedVariable);protectedMethod();}
}public class Main {public static void main(String[] args) {ChildClass child = new ChildClass();child.accessProtectedMembers();}
}

💯public 修饰符

  • 访问权限:可以被任何类访问,无论这些类是否在同一个包中,也无论它们是否存在继承关系。
  • 使用场景:常用于定义公共的 API,如公共类、公共方法和公共常量等,方便其他类使用。
  • 示例代码
// 假设在 com.publicapi 包下
package com.publicapi;public class PublicExample {// 公共成员变量public int publicVariable = 40;// 公共方法public void publicMethod() {System.out.println("This is a public method.");}
}// 可以在任何包中的类中访问公共成员
public class Main {public static void main(String[] args) {PublicExample example = new PublicExample();System.out.println(example.publicVariable);example.publicMethod();}
}

💯归纳

权限修饰符本类同一个包中的类不同包中的子类不同包中的非子类
private可以访问不可访问不可访问不可访问
默认(无修饰符)可以访问可以访问不可访问不可访问
protected可以访问可以访问可以访问不可访问
public可以访问可以访问可以访问可以访问

🦜继承的特点

💯单继承

java只允许单继承,不能使用多重继承,即一个子类只能继承一个父类;也允许多层继承,即一个子类可以继承一个父类,这个父类也可以继承一个父类。

  • 错误代码
class A{}
class B{}
class C extends A,B{}    //同时继承两个类,代码错误
  • 多层继承
class A{}
class B extends A{}
class C extends B{}

💯Object类

在 Java 里,Object 类是所有类的父类,即每个类都直接或间接地继承自 Object 类。这意味着 Java 中的任何对象都能调用 Object 类所定义的方法。

  • 顶级父类:作为 Java 类层次结构的顶端,所有类默认继承它,无需显式声明。
  • 多态基础:由于所有类都继承自 Object 类,所以可以将任何对象赋值给 Object 类型的变量,为多态性提供了基础。

💯就近原则

在子类方法中访问其它成员,是依照就近原则的。

  • 先子类局部范围找,然后子类成员范围找,然后父类成员范围找,如果都未找到就报错。

注意:如果子父类中,出现了重名成员,会优先使用子类的。如果想要在子类中使用父类的,就需要用到super关键字。

格式如下

super.父类成员变量/父类成员方法

代码示例如下

public class Test {public static void main(String[] args) {Zi zi=new Zi();zi.show();}
}
class Fu {String name="父类的name";public void run(){System.out.println("父类的run方法");}
}
class Zi extends Fu{String name="子类的name";public void show(){String name="show的name";System.out.println(name);//show的nameSystem.out.println(this.name);//子类的nameSystem.out.println(super.name);//父类的namesuper.run();//父类的run方法run();//子类的run方法}public void run(){System.out.println("子类的run方法");}}

运行结果:

show的name
子类的name
父类的name
父类的run方法
子类的run方法

✍️方法重写

当子类觉得父类中的某一个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称、参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写(声明不变,重新实现)。

  • 代码示例
public class Test {public static void main(String[] args) {Cat cat = new Cat();cat.eat();}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}
}class Animal {public void eat() {System.out.println("动物吃东西");}
}
  • 运行结果
猫吃鱼

这段代码中,子类Cat继承父类Animal,子类中的eat方法重写了父类中的eat方法,所以输出结果为子类方法中的内容。

💯@Override

在 Java 里,@Override属于注解,其用途是告知编译器,我们打算对父类中的一个方法进行重写。

用途:

  • 编译器检查:借助 @Override 注解,编译器会核查该方法是否确实重写了父类的方法。若没有重写,编译器就会报错,这样能避免因拼写错误或者方法签名不匹配引发的潜在问题。
  • 增强代码可读性:明确表明这个方法是对父类方法的重写,使代码的意图更加清晰。

💯方法重写的注意事项

  • 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限。(public>protected>默认)
  • 重写的方法返回值类型必须与被重写方法的返回值类型一样,或者范围更小。
  • 私有方法、静态方法不能被重写,如果重写会报错。

💯toString方法重写

在 Java 中,toString 方法是 Object 类中的一个方法,所有类都继承自 Object 类,因此都拥有 toString 方法。toString 方法的主要作用是返回对象的字符串表示形式。默认情况下,toString 方法返回的是对象的类名和哈希码,这通常对开发者和用户来说没有太大的实际意义。所以,我们经常会重写 toString 方法,以提供更有意义的对象信息。

注意:

  • 直接输出对象,默认会调用Object类的toString方法(可以省略不写toString的方法)。

以下是一个重写 toString 方法的示例代码,我会为其添加详细的注释并进行简单说明:

// 定义一个名为 Person 的类,用于表示一个人的信息
class Person {// 定义两个私有属性,分别表示人的姓名和年龄private String name;private int age;// 构造函数,用于初始化 Person 对象的姓名和年龄public Person(String name, int age) {// 使用 this 关键字来区分成员变量和局部变量this.name = name;this.age = age;}// 重写 Object 类的 toString 方法,以提供更有意义的对象信息@Overridepublic String toString() {// 返回一个包含姓名和年龄信息的字符串return "Person{name='" + name + "', age=" + age + "}";}
}public class Test {public static void main(String[] args) {// 创建一个 Person 对象,并传入姓名和年龄Person person = new Person("Alice", 25);// 调用 person 对象的 toString 方法,并将结果打印输出System.out.println(person); }
}

代码说明

  1. 类的定义:定义了一个名为 Person 的类,该类有两个私有属性 nameage,分别表示人的姓名和年龄。
  2. 构造函数Person 类的构造函数用于初始化 nameage 属性。
  3. 重写 toString 方法:在 Person 类中重写了 toString 方法,使用 @Override 注解告诉编译器这是一个重写的方法。重写后的 toString 方法返回一个包含 nameage 信息的字符串。
  4. 主方法:在 Test 类的 main 方法中,创建了一个 Person 对象,并调用其 toString 方法将结果打印输出。由于 System.out.println 方法会自动调用对象的 toString 方法,所以可以直接传入 person 对象。

通过重写 toString 方法,我们可以方便地获取对象的详细信息,这在调试和日志记录中非常有用。

补充

  • Object 类中toString方法的源码如下:
public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

🐧子类构造器的特点

  • 子类中的全部构造器,都必须先调用父类的构造器,再执行自己。
  • 使用super(...)可以调用父类有参数构造器,为对象中包含父类这部分的成员变量进行赋值。
public class Test {public static void main(String[] args) {Zi z = new Zi();}
}
class Zi extends Fu {public Zi() {super(666);//指定调用父类的有参构造器System.out.println("子类构造器");}
}class Fu{public Fu() {System.out.println("父类构造器");}public Fu(int a) {System.out.println("父类有参构造器");}
}

运行结果:

父类有参构造器
子类构造器

注意:super关键字必须写在首行。

💯this与super的区别

比较项thissuper
基本含义指代当前对象的引用,即调用方法或构造器的对象本身代表父类(直接超类)的引用,用于访问父类中被覆盖的成员或构造器
主要作用1. 区分成员变量与局部变量(两者同名时);2. 在构造器中调用同一类的其他构造器(需为构造器首行);3. 在方法中引用当前对象1. 在子类构造器中调用父类的构造器(需为子类构造方法首行);2. 访问父类中被覆盖的成员变量或方法(子类重写父类成员时)
使用限制1. 不能在静态方法或静态代码块中使用;2. 构造器中调用其他构造方法时,只能出现一次且必须为第一行1. 子类构造器若未显式调用 super(),编译器会自动插入无参的父类构造器(若父类存在无参构造器);2. 若父类没有无参构造器,子类必须显式调用父类的有参构造器(通过 super(参数)
本质区别操作当前类的成员(包括从父类继承的成员)操作父类的成员(即使子类重写了父类成员,也能通过 super 访问父类的版本)
适用场景访问当前对象成员或构造器访问父类成员或构造器

相关文章:

  • 【Agent python实战】ReAct 与 Plan-and-Execute 的融合之道_基于DeepSeek api
  • 【C++语法】类和对象(1)
  • 什么时候使用Python 虚拟环境(venv)而不用conda
  • 软件设计案例分析学习笔记
  • 单片机-89C51部分:3、创建工程
  • Jmeter数据库url开关设置+常用Beanshell
  • 关于Code_流苏:商务合作、产品开发、计算机科普、自媒体运营,一起见证科技与艺术的交融!
  • FPGA 100G UDP纯逻辑协议栈
  • nuxt3项目搭建:一、初始化项目流程指南
  • 如何在 Windows 10 中使用 WSL 和 Debian 安装 Postgresql 和 Postgis
  • Ext JS模拟后端数据之SimManager
  • 提取PPT图片
  • 关于Android Studio的Gradle各项配置
  • 泰迪杯实战案例学习资料:生产线的故障自动识别和人员配置优化
  • 26 Arcgis软件常用工具有哪些
  • 使用MobaXterm远程登录Ubuntu系统:SSH服务配置教程
  • 微信小程序 - 根据经纬度打开导航
  • 字节 AI 原生 IDE Trae 发布 v1.3.0,新增 MCP 支持
  • AI图像编辑器 Luminar Neo 便携版 Win1.24.0.14794
  • C++:类和对象(上)---镜中万象:C++类的抽象之境与对象的具体之象
  • 广东雷州农商行董事长、原行长同日被查
  • 餐饮店直播顾客用餐,律师:公共场所并非无隐私,需对方同意
  • 五一期间上海景观照明开启重大活动模式,外滩不展演光影秀
  • 柴德赓、纪庸与叫歇碑
  • 李勇已任内蒙古乌兰察布市委副书记,曾在中央编办任职
  • 2025上海浪琴环球马术冠军赛开赛在即,首批赛马今晨抵沪