带你玩转java封装和继承(上)

上次带大家学习了java里面比较重要的知识点类和对象,而且我们知道java是一门面向对象的语言,有时一个程序里可能有很多类,那么这么多类他们之间有什么联系吗?今天就带大家学习一下java类之间的关系。

 

 什么是继承:

我们在日常学习中,在java程序编写时,先创建类,在实例化对象进一步对类进行使用,然而,世界上很多事物往往都不是独立的,他们之间可能存在着千丝万缕的联系,那么如何建立这种联系呢

举个例子创建一个狗类:

//Dog类
public class Dog{String name;String sex;int age;public void bark(){System.out.println(name+"正在汪汪汪");}public void sleep(){System.out.println(name+"正在睡觉")}
}

在定义一个猫类:

public class Cat{
string name;
int age;
string color;
public void sleep()
{
System.out.println(name + "正在睡觉");
}
void mew(){
System.out.println(name + "喵喵喵~~~");
}
}

通过这两个例子我们可以很直观的看到,这两类有太多一样的地方,我们如果可以把这些一样的部分抽离出来,使用时直接调用它,代码效率会大大加强,实现了代码的复用,其实,这就是继承的本质。

继承 (inheritance) 机制 :是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性 的基础上进行扩展,增加新功能 ,这样产生新的类,称 派生类 。继承呈现了面向对象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码用
例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用。
概念可能不太直观,这里我以上面为例,重新写一段程序:

 

public class Animal{String name;int age;public void eat(){System.out.println(name+"正在吃饭");}public void sleep(){System.out.println(name+"正在睡觉");}
}
public class Dog extends Animal{void bark(){System.out.println(name + "汪汪汪~~~");}
}
public class Cat extends Animal{void mew(){System.out.println(name + "喵喵喵~~~");}
}

       我们将Dog类和Cat类称为子类,Animal为父类。 

       这样的话,代码就大大简化当我们再去创建动物对象时,就可以直接调用这里的Animal类中的成员这里的extends是子类继承父类成员时必须使用的关键字。

子类如何访问父类的成员:

子类访问父类的成员,这里分为两种情况:

  1. 子类成员与父类成员名字一致。
  2. 子类成员与父类成员名字不一致。

 子类成员与父类成员名字一致

public 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,还是子类自己新增的a?
b = 101; // 访问父类继承的b,还是子类自己新增的b?
c = 102; // 子类没有c,访问的肯定是从父类继承下来的c
// d = 103; // 编译失败,因为父类和子类都没有定义成员变量b
}
}

这里需要注意的是:

  1. 当父类与子类成员名字一致时,优先访问自己的成员变量。
  2. 当访问成员变量时优先访问自己的,若没有再去访问父类的
  3. 若子类与父类都没有,会发生编译错误。

成员变量是这样,成员方法也是这样,调用成员方法时优先考虑子类自己的,若没有则去父类中查找,都没有就会报错。

public class Base {
public void ways1(){
System.out.println("Base中的ways1()");
}
public void ways2(){
System.out.println("Base中的ways2()");
}
}
public class Derived extends Base{
public void ways1(int a) {
System.out.println("Derived中的way1(int)方法");
}
public void ways2(){
System.out.println("Derived中的ways2()方法");
}
public void ways3(){
ways1(); // 调用的是父类中的因为,父类中午参数
ways1(20); // 传递参数,访问子类中的way1(int)
ways2(); //默认访问子类中的ways2
}
}

 super关键字

上面我们说了,当访问的成员或变量子类与父类同名时,默认访问的是子类的,那么如果就像访问父类的呢?这里就需要使用到super关键字了。他可以在子类方法中访问父类的成员

 

class Country {String name;void value() {name = "China";}
}class City extends Country {String name;void value() {name = "Shanghai";super.value();      //调用父类的方法System.out.println(name);   //默认打印子类中的chinaSystem.out.println(super.name);   //使用super关键字调用父类中的name}public static void main(String[] args) {City c=new City();c.value();}
}

运行结果: Shanghai     China   

在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可。
注意:
  1. super关键字只可以在非静态的方法中访问。
  2. super关键字是在子类中调用父类成员使用的。

子类的构造方法

我们在实例化子类对象时,会调用子类的构造方法,然而其实子类的构造方法在调用之前,编译器已经偷偷地将父类的构造方法调用过一次了,只是没有显示而已,我们可以这样理解,子类中的成员变量,其实是由两部分构成的,一部分是自己的,另一部分是从父类中继承下来的,所以必须先要把从父类中继承的成员变量初始化了,然后才初始化自己的成员变量。

正所谓:父子父子,先有父才能有子。

public class Base {
public Base(){
System.out.println("Base()");
}
}
public class Derived extends Base{
public Derived(){
// super(); 
System.out.println("Derived()");
}
}
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
}

运行结果:Base()   Derived()

总结:

  1. 当父类中显式定义无参或者默认的构造方法,那么在子类中都默认调用了父类无参数的构造方法。
  2. 当自行定义有参数的父类构造方法时,子类的构造方法中不在默认提供调用父类构造方法的操作。需要用户在子类的构造方法中自行调用,否则编译错误。
  3. 当在子类中调用super(),必须将super()放到第一行,否则编译错误。
  4. 在子类的构造方法中不能同时出现super()和this因为从语法上他们都要放到第一行。

 super和this的区别

这里提醒一下,不懂this的uu们,看我的上一篇文章。

this 相当于是指向当前对象本身,可以理解为指向当前对象的指针,(当然java中没有指针只是这样方便理解)。

这里介绍this的几种用法:

  1. .普通的直接引用:直接使用this.×××来引用
  2. 当类中的成员变量与成员函数中的参数同名时,this.成员变量,用来指代当前对象的引用
    class Person {private int age = 10;public Person(){System.out.println("初始化年龄:"+age);
    }public int GetAge(int age){this.age = age;   //调用的是当前对象Harry的age=形参的agereturn this.age;}
    }public class test1 {public static void main(String[] args) {Person Harry = new Person();System.out.println("Harry's age is "+Harry.GetAge(12));}
    }
  3. 用来调用另一种构造方法:
    public class Chinese { Chinese() { System.out.println("无参数构造方法"": "+"A chinese coder."); } Chinese(String name) { System.out.println("含一个参数的构造方法"": "+"his name is " + name); } Chinese(String name, int age) { this(name);// 调用具有相同形参的构造方法(3) System.out.println("两个形参的构造方法:his age is " + age); } public static void main(String[] args) { Chinese cn = new Chinese(); cn = new Chinese("codersai"); cn = new Chinese("codersai", 18); } 
    }

    super可以理解为一个指向父类对象的指针,完成对父类对象的引用。

    普通的直接引用:super.×××引用父类对象的成员变量

    子类中的成员变量或方法与父类中的成员变量或方法同名:使用super.×××来调用父类的成员。

    引用构造函数:子类中的构造方法执行之前要先调用父类中的super(),且必须是第一行。

初始化代码运行顺序

静态代码块执行    实例代码块执行       构造方法执行

这三种代码块的运行顺序是怎么样的呢,

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:静态代码块执行");
}
}
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 TestDemo4 {
public static void main(String[] args) {
Student student1 = new Student("张三",19);
System.out.println("===========================");
Student student2 = new Student("ningzhiyuan",20);

运行结果:

Person :静态代码块执行
Student :静态代码块执行
Person :实例代码块执行
Person :构造方法执行
Student :实例代码块执行
Student :构造方法执行
===========================
Person :实例代码块执行
Person :构造方法执行
Student :实例代码块执行
Student :构造方法执行

       由此我们知道了代码块的执行顺序:父类静态代码块,子类静态方法,父类实例代码块 ,父类构造方法,子类实例代码块,子类构造方法。并且静态代码块只执行一次。

访问限定符

java中为了更好的封装,建立了访问限定符,让数据封装起来,数据更加安全。

 

这些限定符决定了数据在哪里可以使用,哪里不可以使用,对于数据权限的管理非常有效。也提醒我们后面使用数据之前应该了解数据的权限避免写出错误的代码。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux信号【systemV】

目录 前言 正文: 1消息队列 1.1什么是消息队列? 1.2消息队列的数据结构 1.3消息队列的相关接口 1.3.1创建 1.3.2释放 1.3.3发送 1.3.4接收 1.4消息队列补充 2.信号量 2.1什么是信号量 2.2互斥相关概念 2.3信号量的数据结构 2.4…

蓝桥杯-单片机组基础5——外部中断与LED的控制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章:戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写,代码可直接在比赛开发板上使用。 型号:国信天长4T开发板(绿板),芯片:IAP15F2K6…

自学软件测试怎么学?

软件测试是一个变得越来越受欢迎的行业,在IT行业里面,也是初学比较容易的。但对小白而言,怎样学习才能做到快速入门,少走弯路呢? 步骤一:初学学软件测试,要先搞懂这种问题 要想进入到软件测试…

Android Duplicate class 排除重复类

一、起因: 在迭代开发的时候,发现2个ijk很多类重复。但又2个库实现的功能是不一样,目前不能合并。但又想保留2个功能。需要排除其中一个库。 二、报错如何下图: 三、解决方法: 3.1 在terminal 也就是命令行处输入 …

在Windows 11中运行磁盘清理工具的9种方法,总有一种适合你

自Windows98以来,微软在操作系统中包含了一个内置的清理工具。当用户转向第三方清理应用程序时,这个值得信赖的实用程序站稳了脚跟。微软甚至宣布,第三方应用程序几乎毫无用处,删除注册表项不是一个好主意。 磁盘清理工具可以帮助删除临时文件、旧的更新日志、缩略图缓存和…

git安装与使用4.3

一、git的安装 1、下载git包 下载git包url:https://git-scm.com/download/win 下载包分为:64位和32位 2、点击安装包 2、选择安装路径 3、 点击下一步 4、点击next 5、点击next 6、点击next 7、 8、 9、 10、 11、 12、在桌面空白处,右键…

【SpringBoot】测试单元使用多线程

📝个人主页:五敷有你 🔥系列专栏:SpringBoot ⛺️稳重求进,晒太阳 问题产生 今天学习了乐观锁,但在测试单元执行多线程的时候出现了问题,多线程并没有直接结果 在控制台没有任何输出…

KubeSphere平台安装系列之二【Linux单节点部署KubeSphere】(2/3)

**《KubeSphere平台安装系列》** 【Kubernetes上安装KubeSphere(亲测–实操完整版)】(1/3) 【Linux单节点部署KubeSphere】(2/3) 【Linux多节点部署KubeSphere】(3/3) **《KubeS…

RocketMQ学习笔记一

课程来源:002-MQ简介_哔哩哔哩_bilibili (尚硅谷老雷,时长19h) 第1章 RocketMQ概述 1. MQ是什么? 2. MQ用途有哪些? 限流削峰;异步解耦;数据收集。 3. 常见MQ产品有哪些&对比…

Kaggle竞赛之Titanic存活预测2

提高代码规范性,基于上一个 baseline 的提高 import pandas as pd from sklearn.preprocessing import LabelBinarizer from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split#数据划分方法 from sklearn.ensem…

哪个超声波清洗机品牌值得入手?销量榜品牌值得选购!

在科技日益发展的今天,超声波清洗技术以其高效、便捷和深度清洁的特点,已经深入到生活的诸多领域,从精密仪器到珠宝首饰,从眼镜框到假牙,甚至是厨房用品的日常护理,都能见到超声波清洗机的身影。面对市场上…

免杀实战-EDR对抗

文章目录 杀软分析BOF.NET 杀软分析 x64dgb简单调试发现该edr在r3环对ntdll.dll和kernel32.dll关键函数均存在hook,这里硬盘读取原来的dll进行重新加载,原理如图 loader // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" #in…

DSI2协议之BTA行为理解

概念: DSI协议spec支持总线控制权在master和slave之间发生交换,即通过bus turn around来实现; BUS TURN AROUND: BTA 的实现是通过controller—>cdphy的turnrequest信号来实现; 关于控制器发出turnrequest给phy,phy通过lvds/trio线输出turnaround sequence如下图中…

BUGKU 本地管理员

打开环境,先F12查看看到一串代码。Base64解码一下,得到的应该是密码,然后输入admin | test123试一下 使用BP抓包,修改XFF,得到flag

将镜像上传到私有镜像仓库Harbor

首先你需要安装Harbor服务: https://blog.csdn.net/qq_50247813/article/details/136388229 客户端已经安装docker: https://docs.docker.com/engine/install/centos/ 在docker客户端登录 Harbor 我的Harbor 服务器地址: 192.168.44.161 账号…

关于编写测试用例的一些思考

测试用例是QA同学的基本功,每个人都有一套编写测试用例的体系,本文是作者结合自身的工作经验以及阅读一些测试相关的书籍后的一些看法,欢迎大家一起讨论学习。 测试设计 测试用例格式 面试中一些常见的问题 1.APP测试与服务端测试的区别&am…

何恺明新作 l-DAE:解构扩散模型

何恺明新作 l-DAE:解构扩散模型 提出背景扩散模型步骤如何在不影响数据表征能力的同时简化模型?如何进一步推动模型向经典DAE靠拢?如何去除对生成任务设计的DDM中不适用于自监督学习的部分?如何改进DDM以专注于清晰图像表示的学习…

2024华为软件测试笔试面试真题,抓紧收藏不然就看不到了

一、选择题 1、对计算机软件和硬件资源进行管理和控制的软件是(D) A.文件管理程序 B.输入输出管理程序 C.命令出来程序 D.操作系统 2、在没有需求文档和产品说明书的情况下只有哪一种测试方法可以进行的(A) A.错误推测法测试…

Docker 快速入门实操教程(完结)

Docker 快速入门实操教程(完结) Docker,启动! 如果安装好Docker不知道怎么使用,不理解各个名词的概念,不太了解各个功能的用途,这篇文章应该会对你有帮助。 前置条件:已经安装Doc…

IOS 发布遇到“Unable to authenticate with App Store Connect”错误咋解决?

问题: 在开发ios app后,先发布adhoc版本,测试通过后,再发布testflight版本测试,但是可能会遇到一下问题。 解决办法: 在Signing &Capabilities中,在ios下边要指定有发布权限的Team账号&a…