Java继承教程!(o|o)

Java 继承

Java面向对象设计 - Java继承

子类可以从超类继承。超类也称为基类或父类。子类也称为派生类或子类。

从另一个类继承一个类非常简单。我们在子类的类声明中使用关键字extends,后跟超类名称。

Java不支持多重继承的实现。

Java中的类不能有多个超类。

语法

一般的语法是

<class modifiers>class <SubclassName> extends <SuperclassName> {// Code for the   Subclass
}

例子

以下代码显示如何使用从Employee类创建Manager类。

class Employee {private String name = "Unknown";public void setName(String name) {this.name = name;}public String getName() {return name;}
}
class Manager extends Employee {
}
public class Main {public static void main(String[] args) {// Create an object of the Manager classManager mgr = new Manager();// Set the name of the managermgr.setName("Tom");// Get the name of the managerString mgrName = mgr.getName();// Display the manager nameSystem.out.println("Manager Name: " + mgrName);}
}

上面的代码生成以下结果。

注意

我们没有为Manager类编写任何代码,它的工作原理与Employee类相同,因为它继承自Employee类。

您可以使用Manager类的构造函数创建一个管理器对象。

Manager mgr = new Manager();

创建管理器对象后,Manager对象的工作方式与Employee对象相同。

我们对manager对象使用了setName()和getName()方法。

mgr.setName("Tom"); 
String mgrName  = mgr.getName();

Manager类不声明setName()和getName()方法。Manager类“扩展Employee"。

当一个类从另一个类继承时,它继承它的超类成员,实例变量,方法等。

对象父类

对象类是默认超类。

所有类都隐式继承自Object类。因此所有类的对象都可以使用Object类的方法。

public class P {}

类P从Object扩展,即使我们没有指定父类。

Object类声明了hashCode()和toString()方法。因为Employee类是Object类的一个子类,它可以使用这些方法。

Employee emp = new Employee();
int hc  = emp.hashCode(); 
String str = emp.toString();

Employee类不使用extends子句指定其超类。这意味着它继承自Object类。

Object类声明了hashCode()和toString()方法。因为Employee类是Object类的一个子类,它可以使用这些方法。

向上转换和向下转换

现实世界中的“is-a”关系在软件中转化为继承类层次结构。

例如,Manager是特定类型的Employee。 Employee是一种特定类型的Object。

当您在继承层次结构中向上移动时,将从特定类型移动到更一般的类型。

从子类到超类的赋值称为上转换,它在Java中始终允许。

class Employee {private String name = "Unknown";public void setName(String name) {this.name = name;}public String getName() {return name;}
}class Manager extends Employee {
}public class Main {public static void printName(Employee emp) {String name = emp.getName();System.out.println(name);}public static void main(String[] args) {Employee emp = new Employee();emp.setName("Tom");Manager mgr = new Manager();mgr.setName("Jack"); // Inheritance of setName() at work// Print namesprintName(emp);printName(mgr); // Upcasting at work}
}

为子类变量分配超类引用称为向下转换。

向下转换与向上转换相反。

在向上转换中,赋值向上移动类层次结构,而在向下转换中,赋值向下移动类层次结构。

我们必须在向下转换中使用类型转换。

Manager mgr = (Manager)emp;  // OK. Downcast  at work

上面的代码生成以下结果。

instanceof运算符

Java instanceof运算符帮助我们确定引用变量是否有对类或子类的引用。

它需要两个操作数,并计算为布尔值true或false。

它的语法是

<Class Reference Variable> instanceof <Class Name or Interface>

如果<Class Reference Variable>引用类<Class Name>或其任何后代的对象,instanceof返回true。

如果引用变量为null,instanceof总是返回false。

我们应该在向下转换之前使用instanceof运算符。

Manager mgr = new Manager(); 
Employee emp = mgr;
if (emp instanceof Manager)  {// downcast  will succeed mgr = (Manager)emp;
}else  {// emp is not  a  Manager type
}

禁用继承

我们可以通过声明类final来禁用子类。

最终的类不能被子类化。

下面的代码声明了一个名为MyClass的最终类:

public final  class  MyClass{}

我们也可以声明一个方法为final。最终方法不能被子类覆盖或隐藏。

public class A  {public final  void  m1()  {}public void  m2()  {}
}

Java 方法重写

Java面向对象设计 - Java方法重写

方法重写

重新定义从超类继承的类中的实例方法称为方法重写。

例子

让我们考虑类A和类B的以下声明:

public class A  {public void  print() { System.out.println("A");}
}public class B  extends A  {public void  print() { System.out.println("B");}
}

类B是类A的子类。类B从其超类继承print()方法并重新定义它。

类B中的print()方法覆盖类A的print()方法。

如果一个类覆盖了一个方法,它会影响覆盖的类及其子类。考虑下面的类C的声明:

public class C  extends B  {// Inherits B.print()
}

类C不声明任何方法。它继承类B中的print()方法。

注意

类总是继承它的直接超类的可用的。

方法必须是实例方法。重写不适用于静态方法。

重写方法必须具有与重写方法相同的名称。

重写方法必须具有与重写方法相同顺序的相同类型的相同数量的参数。

当方法的参数使用通用类型时,考虑通用类型参数的擦除,而不是通用类型本身与其他方法比较。

参数的名称无关紧要。

如果重写方法的返回类型是引用类型,则重写方法的返回类型必须与重写方法的返回类型兼容。

访问级别

重写方法的访问级别必须至少与重写方法的访问级别相同或更宽松。

下表列出了重写方法允许的访问级别

重写方法访问级别允许重写方法访问级别...
publicpublic
protectedpublic, protected
package-levelpublic, protected, package-level

方法可以在其throws子句中包括检查异常的列表。重写方法无法向重写方法中的异常列表添加新的异常。

它可以删除一个或所有异常,或者可以用另一个异常替换异常。

访问重写方法

从子类访问重写的方法。子类可以使用关键字 super 作为限定符来调用超类的重写方法。

class MySuperClass {public void print() {System.out.println("Inside MySuperClass");}
}class MySubClass extends MySuperClass {public void print() {// Call print() method of MySuperClass classsuper.print();// Print a messageSystem.out.println("Inside MySubClass.print()");}public void callOverridenPrint() {// Call print() method of MySuperClass class super.print();}
}public class Main {public static void main(String[] args) {MySubClass aoSub = new MySubClass();aoSub.print();aoSub.callOverridenPrint();}
}

上面的代码生成以下结果。

Java 继承和构造函数 

Java面向对象设计 - Java继承和构造函数

构造函数不是类的成员,它们不是由子类继承的。

它们用于初始化实例变量。

class CSuper {public CSuper() {System.out.println("Inside CSuper() constructor.");}
}class CSub extends CSuper {public CSub() {System.out.println("Inside CSub()  constructor.");}
}public class Main {public static void main(String[] args) {CSub cs = new CSub();}
}

上面的代码生成以下结果。

例子

下面显示了如何编译器注入一个super()来立即调用父类的无参数构造函数。

class CSuper {public CSuper() {super(); // Injected by the compilerSystem.out.println("Inside CSuper() constructor.");}
}class CSub extends CSuper {public CSub() {super(); // Injected by the compilerSystem.out.println("Inside CSub()  constructor.");}
}public class Main {public static void main(String[] args) {CSub cs = new CSub();}
}

上面的代码生成以下结果。

关键字super指的是类的直接父类。

我们可以调用超类构造函数,只使用super关键字作为构造函数中的第一个语句。

无参数构造函数

我们可以将超类的no-args构造函数或任何其他构造函数显式地调用为类的构造函数中的第一个语句。

只有在没有明确添加的情况下,编译器才会注入no-args构造函数调用。

class Employee {private String name = "Unknown";public Employee(String name) {this.name = name;}public void setName(String name) {this.name = name;}public String getName() {return name;}
}class Manager extends Employee {public Manager(String name) {super(name);}
}public class Main {public static void main(String[] args) {Manager mgr = new Manager("Tom");String name = mgr.getName();System.out.println("Manager name:  " + name);}
}

上面的代码生成以下结果。

每个类都必须直接或间接地从其构造函数中调用其超类的构造函数。

如果超类没有no-args构造函数,我们必须显式地调用超类的任何其他构造函数。

Java 继承隐藏

Java面向对象的设计 - Java继承隐藏

方法隐藏

类从其超类继承所有非私有静态方法。

重定义类中继承的静态方法称为方法隐藏。

子类中的重定义静态方法隐藏其超类的静态方法。

在类中重定义非静态方法称为方法覆盖。

关于方法隐藏的重定义方法(名称,访问级别,返回类型和异常)的所有规则与方法覆盖相同。

class MySuper {public static void print() {System.out.println("Inside MySuper.print()");}
}class MySubclass extends MySuper {public static void print() {System.out.println("Inside MySubclass.print()");}
}public class Main {public static void main(String[] args) {MySuper mhSuper = new MySub();MySubclass mhSub = new MySubclass();MySuper.print();MySubclass.print();((MySuper) mhSub).print();mhSuper = mhSub;mhSuper.print();((MySubclass) mhSuper).print();}
}

上面的代码生成以下结果。

字段隐藏

类中的字段声明(静态或非静态)在其父类中隐藏具有相同名称的继承字段。

在字段隐藏的情况下,不考虑字段的类型及其访问级别。

字段隐藏仅基于字段名称。

class MySuper {protected int num = 100;protected String name = "Tom";
}class MySub extends MySuper {public void print() {System.out.println("num: " + num);System.out.println("name: " + name);}
}class MySub2 extends MySuper {// Hides num field in MySuper classprivate int num = 200;// Hides name field in MySuper classprivate String name = "Jack";public void print() {System.out.println("num: " + num);System.out.println("name: " + name);}
}public class Main {public static void main(String[] args) {MySub fhSub = new MySub();fhSub.print();MySub2 fhSub2 = new MySub2();fhSub2.print();}
}

上面的代码生成以下结果。

例子

以下代码显示了如何使用super关键字访问超类的隐藏字段

class MySuper {protected int num = 100;protected String name = "Tom";
}class MySub extends MySuper {// Hides the num field in MySuper classprivate int num = 200;// Hides the name field in MySuper classprivate String name = "Jack";public void print() {System.out.println("num: " + num);System.out.println("super.num: " + super.num);System.out.println("name: " + name);System.out.println("super.name: " + super.name);}
}public class Main {public static void main(String[] args) {MySub s = new MySub();s.print();}
}

上面的代码生成以下结果。

字段隐藏发生在一个类声明一个变量与来自其超类的继承变量具有相同名称的时候。

字段隐藏仅基于字段的名称。

类应该使用关键字super来访问超类的隐藏字段。

类可以使用简单的名称来访问其主体中的重定义字段

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147560.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

SwiftUI 实现关键帧动画

实现一个扫描二维码的动画效果&#xff0c;然而SwiftUI中没有提供CABasicAnimation 动画方法&#xff0c;该如何实现这种效果&#xff1f;先弄清楚什么关键帧动画&#xff0c;简单的说就是指视图从起点至终点的状态变化&#xff0c;可以是形状、位置、透明度等等 本文提供了一…

pytorch学习笔记二:用pytorch神经网络模型做气温预测、分类任务构建

文章目录 一、搭建pytorch神经网络进行气温预测1&#xff09;基础搭建2&#xff09;实际操作标识特征和标签3&#xff09;构建成标准化的预处理数据&#xff08;做标准化收敛速度更快&#xff09; 二、按照建模顺序构建完成网络架构1&#xff09;np.array格式的标签(y)和特征(x…

Spring Boot管理用户数据

目录 学习目标前言Thymeleaf 模板JSON 数据步骤 1: 创建 Spring Boot 项目使用 Spring Initializr 创建项目使用 IDE 创建项目 步骤 2: 添加依赖步骤 3: 创建 Controller步骤 4: 新建index页面步骤 5: 运行应用程序 表单提交步骤 1: 添加 Thymeleaf 依赖在 Maven 中添加依赖 步…

Github 2024-09-22 php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-09-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10Blade项目1Coolify: 开源自助云平台 创建周期:1112 天开发语言:PHP, Blade协议类型:Apache License 2.0Star数量:10527 个Fork数量…

串的存储实现方法(与链表相关)

一、 定义 字符串是由零个&#xff08;空串&#xff09;或多个字符组成的有限序列。 eg:S"Hello World!" 串相等&#xff1a;两个串长度相等并且对应位置的字符都相等时&#xff0c;两个串才相等。 二、串的存储实现 2.1 定长顺序串 2.2 堆串 和定长顺序串的…

nodejs 014: React.FC 与 Evergreen(常青树) React UI 框架的的Dialog组件

React.FC React.FC是React中用于定义函数组件“Function Component”的类型。它代表&#xff0c;可以帮助你在TypeScript中提供类型检查和自动补全。使用React.FC时&#xff0c;可以明确指定组件的props类型&#xff0c;并且它会自动推导children属性。下面是一个使用 React.F…

二、MySQL环境搭建

文章目录 1. MySQL的卸载步骤1&#xff1a;停止MySQL服务步骤2&#xff1a;软件的卸载步骤3&#xff1a;残余文件的清理步骤4&#xff1a;清理注册表&#xff08;选做&#xff09;步骤5&#xff1a;删除环境变量配置 2. MySQL的下载、安装、配置2.1 MySQL的4大版本2.2 软件的下…

Ubuntu以及ROS的一些方便设置及使用

目录 增加环境变量 取消终端sudo密码 关闭开机密码 编写sh文件 虚拟环境的启用与关闭 launch文件小技巧 增加环境变量 1.在home目录下按ctrlh打开隐藏文件&#xff0c;打开.bashrc直接修改即可 2.输入gedit/vim ~/.bashrc修改即可 对于source ~/.bashrc这条指令只是适用…

从零开始讲DDR(5)——读懂Datasheet

对于开发人员来说&#xff0c;需要根据实际场景和使用的需要&#xff0c;使用不同厂家&#xff0c;不同型号的DDR&#xff0c;虽然原理上大同小异&#xff0c;但是还是有一些细节上的需要注意的地方&#xff0c;接触一个新的DDR芯片&#xff0c;首先就是需要找到对应的datashee…

软考高级:系统安全分析与设计- 加密管理:PKI 和 KMI 区别

讲解 PKI&#xff08;公钥基础设施&#xff09;和 KMI&#xff08;密钥管理基础设施&#xff09;都是与加密和密钥管理相关的重要概念&#xff0c;但它们有不同的侧重点。接下来&#xff0c;我将通过一个生活化的例子和概念讲解&#xff0c;帮助你理解它们的区别。 生活化例子…

【redis-02】深入理解redis中RBD和AOF的持久化

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756 如需转载&#xff0c;请输入&#xff1a;htt…

[Java EE] 网络原理 ---- UDP协议 序列化 / 反序列化 长短连接

Author&#xff1a;MTingle major:人工智能 Build your hopes like a tower! 文章目录 文章目录 一. UDP 协议 1.UDP协议的特点 2. UDP 的结构 3. md5算法 二. 长短连接 协程 IO多路复用 序列化和反序列化 1.长短连接 2. 协程 3. IO 多路复用 4.序列化 / 反序列化 一…

队列+宽搜专题篇

目录 N叉树的层序遍历 二叉树的锯齿形层序遍历 二叉树最大宽度 在每个树行中找最大值 N叉树的层序遍历 题目 思路 使用队列层序遍历来解决这道题&#xff0c;首先判断根节点是否为空&#xff0c;为空则返回空的二维数组&#xff1b;否则&#xff0c;就进行层序遍历&#x…

论文阅读 | 可证安全隐写(网络空间安全科学学报 2023)

可证安全隐写&#xff1a;理论、应用与展望 一、什么是可证安全隐写&#xff1f; 对于经验安全的隐写算法&#xff0c;即使其算法设计得相当周密&#xff0c;隐写分析者&#xff08;攻击者&#xff09;在观察了足够数量的载密&#xff08;含有隐写信息的数据&#xff09;和载体…

6.数据库-数据库设计

6.数据库-数据库设计 文章目录 6.数据库-数据库设计一、设计数据库的步骤二、绘制E-R图三、关系模式第一范式 (1st NF)第二范式 (2nd NF)第三范式 (3nd NF)规范化和性能的关系 一、设计数据库的步骤 收集信息 与该系统有关人员进行交流、座谈&#xff0c;充分了解用户需求&am…

Vulkan 学习(9)---- vkSuraceKHR 创建

目录 OverView创建窗口表面参考代码 OverView Vulkan 是一个平台无关的图形API&#xff0c;这意味着它不能直接与特定的窗口系统(Windows&#xff0c;linux 和 macOS 的窗口系统)进行交互 为了解决这个问题&#xff0c;Vulkan 引入了窗口系统集成(Window System Intergration …

DOM【JavaScript】

在JavaScript中&#xff0c;DOM (Document Object Model&#xff1a;文档对象模型) 是web页面的编程接口&#xff0c;用于表示和操作 HTML 和 XML 文档。它将文档结构化为一个树形结构&#xff0c;允许开发者通过 JavaScript 访问和修改网页的内容、结构和样式。以下是一些关于…

基于单片机的智能校园照明系统

由于校园用电量较大&#xff0c;本设计可以根据实际环境情况的改变&#xff0c;实现实时照明的控制。本设计以单片机芯片为控制芯片&#xff0c;热释电传感器采集教室中学生出入的信息&#xff0c;并把信息传递给单片机芯片&#xff0c;单片机芯片根据传感器传递过来的信息来控…

【软件测试】Bug 篇

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 今天给大家带来的是 【软件测试】Bug 篇&#xff0c;首先了解, 什么是Bug, 如何定义一个Bug, 如何描述一个 Bug, Bug的级别, 和 Bug 的生命周期, 以及测试人员跟开发人员产生争执如何处理,…

【MYSQL】聚合查询、分组查询、联合查询

目录 聚合查询聚合函数count()sum()avg()max()和min()总结 分组查询group by 子句having 子句 联合查询笛卡尔积内连接外连接自连接子查询单行子查询多行子查询from子句使用子查询 合并查询 聚合查询 聚合查询就是针对表中行与行之间的查询。 聚合函数 count() count(列名)&a…