Java 类和对象详解(下)

个人主页:鲤鱼王打挺-CSDN博客

 

目录

💗前言:

💯一.static关键字

1. 为什么要使用static

2.  static 修饰成员变量:

 3.  static 修饰成员方法:

​编辑

4. 静态代码块 

 5.静态导入包

💯二.代码块

 1.实例代码块 

 2.静态代码块

3.普通代码块

💯三.继承

1.(过渡)toString方法

 2.为什么需要继承?

3.如何使用继承?

4.super关键字

5.子类 构造方法

6.代码块 

7.继承方式 

8.组合

9.protect 关键字 

💯四.小结


 

💗前言:

  上一篇文章(Java 类和对象详解(上 )-CSDN博客)中我们详细提到了类与对象的组成成分如下图,在明白什么是成员方法,什么是构造方法后,我们今天用不一样的方法来了解什么是静态以及类和对象中的其他组成部分!(无奖竞猜:大家可以找找下图中有什么错误)

💯一.static关键字

为什么要把static修饰符放到这么后面来讲呢?其实大家在学习Java时一开始就会接触static关键字,就是我们的main方法,而且大家在学校,老师可能在学习类的第一堂课就在提到它。

但是我这篇文章是起到给大家梳理的作用,所以我们一块一块的提及,static包括成员方法,成员变量以及代码块(重点是静态代码块,所以必须先知道什么是静态)等都会 使用,所以我们单独列出来一级。

废话不多说,我们先来看看什么是静态:

1. 为什么要使用static

当我们创建一个学生类,创建对象时,三个学生的班级是一样的,此时重复定义classroom变量不仅 麻烦,而且占用了内存空间所以当出现重复变量时,我们就不再让他重复开辟一段新的内存,此时就要用到static。

2.  static 修饰成员变量:

我们学习了局部变量和成员变量,成员变量也叫做实例变量,可以理解为"对象局部变量",而在成员变量前加上static时,称为"类变量",也叫做静态变量所以在定义类时,没有加上static的,都是成员变量。(前言中的图片中其中一个错误就是成员变量不能分成静态和非静态)

类变量可以理解为和类平起平坐,也可以说它的类型是一个类 类型而不属于对象。所以我们无需创建对象,也可以引用静态变量。 此时调试后发现,每个对象中的成员不包含classroom了。我们知道对象存储在堆中,而对象变量并不存储在栈中,而在方法区中。

 

我们可以直接用类名访问它(Student.classroom)  ,虽然我们可以再使用对象来引用它,但是无论你创建几个对象,它都是同一个classroom,不会开辟新的空间了。(这里并不建议用对象来访问它)

 3.  static 修饰成员方法:

 

如上图,此时报错:空指针异常。 当我们为ret方法加上static,使其变成一个静态方法。

可以发现,方法正常被调用,且可以直接用类名调用,这是因为static不依赖于任何对象!

 在1.中我们可以发现,调用类类型,小编是将它定义为public,那么如果我们让它变成我们常用的private,要怎么调用呢?

静态成员一般是通过 静态方法来访问的。

注意:(1)不能在静态方法中访问任何非静态成员变量 

           (2)静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用(因为已经不属于对象了)

           (3)普通成员方法是可以调用静态方法的 

此时我们再回过头看看main方法和普通方法,为什么要加static? 

因为这样我们就可以在main方法中不需要对象来调用方法了。是不是恍然大悟了呢,学习就是一个先完善再完美的过程。。。

注意:静态修饰后,它的生命周期随着类的加载而创建,随类的卸载而销毁 (后文会提到)。

4. 静态代码块 

静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性。 静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。 这就引出我们的代码块——>静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的

 5.静态导入包

import java.util.*;
public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int a = sc.nextInt();}
}

此时我们导入的包是java.util,而 * 是通配符,包含了Scanner类,所以这串代码可以正常运行。 

import java.util.Scanner;
import static java.lang.Math.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int a = sc.nextInt();double ret = Math.sqrt(Math.pow(a,2));double r = sqrt(pow(a,2));}
}

而静态导入后,导入所有静态方法,这样就不用带上类名了(不依赖对象),也算是小小的便利。 

💯二.代码块

使用 {} 定义的一段代码称为代码块,是类的一部分。

根据代码块定义的位置以及关键字,又可分为以下四种:

(1)普通代码块

(2)实例代码块

(3)静态代码块

(4)同步代码块 【小编暂时不提及】

 1.实例代码块 

构造块:定义在类中的代码块(不加修饰符), 也叫:实例代码块。构造代码块一般用于初始化实例成员变量。实例代码块只有在创建对象时才会执行。

{this.name = name;this.gender = gender;
}

 2.静态代码块

静态代码块一般用于初始化静态成员变量。

 static{classRoom = "夯大力123";System.out.println("静态代码块执行了");}

静态代码块也不能调用非静态的变量或方法,因为它不依赖于对象。

静态代码块是最先执行的(加载时就执行),且只执行一次,即使创建了多个对象。 

3.普通代码块

在方法中的代码块就是普通代码块,在代码块中的变量是代码块局部变量,代码块外无法调用。

public class Main{public static void main(String[] args) {
{ {int x = 10 ;System.out.println("x1 = " +x);}{int x = 100 ;System.out.println("x2 = " +x);}
}//x1 = 10   x2 = 100

一般来说,最先执行静态代码块,实例代码块次之,构造方法再执行。如果有多个静态代码块,那么按定义的顺序执行。

💯三.继承

1.(过渡)toString方法

当我们打印对象名的时候,我们会得出类名+@+数字的字符串 ,观察源码可以发现,println方法是调用了系统的toString方法。那么我们能不能调用自己的toStrting方法呢?

如下图: 这是什么原理呢?这就需要搬出我们的继承和多态。

public String toString(){return "name:"+name;}

 2.为什么需要继承?

 观察下方代码,Cat和Dog都有相同的成员变量,这样我们很难不联想到,能不能用Animal类来管理这两个类,这就是继承。

public  class Cat {public String name;public String color;public int age;public void say(){System.out.println(name+"喵喵");}}public class Dog {public String name;public String color;public int age;
}

继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特 性 的基础上进行扩展,增加新功能,这样产生新的类,称派生类。

继承呈现了面向对象程序设计的层次结构, 体现了 由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用。

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

3.如何使用继承?

 我们一般将需要继承的类如Animal称为父类/超类/基类,而Dog称为子类/派生类。继承之后,子类可以复用父类中成员,子类在实现时只需关心自己新增加的成员即可。

继承格式如下:需要使用关键extends(注意不要漏掉s)

public  class Cat extends Animal {public String var;public void say(){System.out.println(name+"喵喵");}
}

子类继承父类之后,必须要新添加自己特有的成员,体现出与基类的不同,否则就没有必要继承 

4.super关键字

当父类不存在与子类同名的成员时,子类直接访问父类成员。

如果父类与子类成员同名时,优先访问子类自己的。

朋友们此时如果使用this,会发现也是访问当前对象也就是子类成员。

而使用super关键字,就可以访问父类成员,成员方法也是如此。

class Animal {public String name;public String color;public int age;public int a = 222;public int b = 333;
}public  class Cat extends Animal {public int a = 111;public String var;public void test(){System.out.println("1:"+a);System.out.println("2:"+this.a);System.out.println("3:"+super.a);System.out.println("4:"+this.b);System.out.println("5:"+super.b);}
}

 

此时重写方法与父类方法同名,需要调用父类方法时,就需要用super方法。 

继承中也存在重载。

注意:

1. 只能在非静态方法中使用(this也是)

2. 在子类方法中,访问父类的成员变量和方法。super.+父类方法名()

3.为了提高代码的可读性,调用父类成员最好使用super关键字。

5.子类 构造方法

子类也会默认初始化无参构造方法,但当我们在构造子类构造器时会报错,这就是前文所说的"救急不救穷",系统不会再初始化无参构造器,所以我们要为父类添加构造器。可以记为:没有父哪有子?

注意:

1.在子类构造方法第一行默认有隐含的super()调用,即调用父类构造方法。

2.在子类构造方法中,super(...)调用父类构造时,必须是子类构造函数中第一条语句。  super(...)只能在子类构造方法中出现一次,并且不能和this同时出现。

小编发现这句有点误导,因为使用了super调用构造后,仍可以用this初始化对象,只是不能再用this调用方法了,因为this也要求在构造器的首行。如下图:

6.代码块 

在子类也能加入代码块,静态代码块是最先执行的。

 下图代码中打印的数字是执行顺序,可以发现是严格按照静态代码块先执行,父类实例优于子类实例,父类构造优于子类构造,由于实例代码块是对象被创建时执行,所以父类构造先于子类的实例代码块

class Animal {public String name;public String color;public int age;static{System.out.println("1 ");}{System.out.println("3");}public Animal(String name, int age){this.name = name;this.age = age;System.out.println("4");}}
public  class Cat extends Animal {public String var;static{System.out.println("2");
}{System.out.println("5");}public Cat(String name, int age){super(name, age);System.out.println("6");}

7.继承方式 

Java类有这几种继承方式,可以继承给子类,子类再继承给它的子类。

也可以父类继承给多个子类。

但是不允许多个父类的情况。 

 

当我们使用final关键字时,说明这个类无法被继承! 

8.组合

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

//汽车
public class Car {private Tire t;private Engine e;}
//轮胎
public class Engine {public int a;public int b;public int c;public int d;
}
//发动机
public class Tire {public int a;public int b;public int c;public int d;
}

 但是组合时,整体类不能自动获得局部类同样的接口,需要再创建类 对象,不像继承无需再创建

9.protect 关键字 

前文我们就提到protect,它的权限范围就是同一个包时,都可以访问;若是不同包,则只有父类的子类才可以访问成员。 

// extend01包中
public class B {
private int a;
protected int b;
public int c;
int d;
}
// extend01包中
// 同一个包中的子类
public class D extends B{
public void method(){
// super.a = 10; // 编译报错,父类private成员在相同包子类中不可见
super.b = 20; // 父类中protected成员在相同包子类中可以直接访问
super.c = 30; // 父类中public成员在相同包子类中可以直接访问
super.d = 40; // 父类中默认访问权限修饰的成员在相同包子类中可以直接访问
}
}
// extend02包中
// 不同包中的子类
public class C extends B {
public void method(){
// super.a = 10; // 编译报错,父类中private成员在不同包子类中不可见
super.b = 20; // 父类中protected修饰的成员在不同包子类中可以直接访问

💯四.小结

类与对象的成员包括什么?继承的细节在哪里体现?小编已经为大家制作了一篇文章供大家参考 

暂时就提到这里,小编还在对知识进行梳理!希望朋友们点点赞支持一下! 

 

 

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

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

相关文章

Wi-Fi安全性入门(基于ESP-IDF-v4.4)

主要参考资料: Wi-Fi 安全性: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.4/esp32/api-guides/wifi-security.html 目录 1.ESP32 Wi-Fi 安全功能1.1 受保护的管理帧 (PMF)1.2 第三代 Wi-Fi 访问保护 (WPA3-Personal) 1.ESP32 Wi-Fi 安全功能 支…

linux系统之jar启动脚本

编辑linux启动脚本 执行 vi run_blog 按i 进入编辑,复制以下代码,并根据当前环境修改三个参数。以下是详细完整脚本代码: #!/bin/bash# 配置部分 JAR_PATH"/path/to/your/app.jar" # 替换为你的 JAR 文件的实际路径 L…

Gin框架操作指南07:路由与中间件

官方文档地址(中文):https://gin-gonic.com/zh-cn/docs/ 注:本教程采用工作区机制,所以一个项目下载了Gin框架,其余项目就无需重复下载,想了解的读者可阅读第一节:Gin操作指南&#…

【JVM】内存模型

文章目录 内存模型的基本概念案例 程序计数器栈Java虚拟机栈局部变量表栈帧中局部变量表的实际状态栈帧中存放的数据有哪些 操作数栈帧数据 本地方法栈 堆堆空间是如何进行管理的? 方法区静态变量存储 直接内存直接内存的作用 内存模型的基本概念 在前面的学习中,我们知道了字…

Java 8 Stream API:从基础到高级,掌握流处理的艺术

一、Stream(流)基本介绍 Java 8 API 添加了一个新的抽象称为Stream(流),可以让你以一种声明的方式处理数据,这种风格将要处理的元素集合看做一种流,元素流在管道中传输,并在管道中间…

云黑系统全解无后门 +搭建教程

这套系统呢是玖逸之前南逸写的一套云黑系统,功能带有卡密生成和添加黑名单等,源码放在我的网盘里已经两年之久,由于玖逸现在已经跑路了所以现在发出来分享给大家,需要的可以自己拿去而开,反正功能也不是很多具体的自己…

电脑视频剪辑大比拼,谁更胜一筹?

随着短视频的火爆,越来越多的人开始尝试自己动手制作视频,无论是记录生活点滴还是创作个性短片,一款好用的视频剪辑软件是必不可少的。今天,我们就从短视频运营的角度,来聊聊几款热门的电脑视频剪辑软件,看…

docker配置加速器

阿里云 控制台》容器镜像服务》镜像工具》镜像加速器 复制地址:https://ywtoq7bz.mirror.aliyuncs.com 到:etc/docker下:vi daemon.json 格式: { "registry-mirrors": ["加速器地址"] } 注&#xff1…

JavaScript:闭包、防抖与节流

一,闭包 1,什么是闭包 闭包是指一个函数和其周围的词法环境(lexical environment)的组合。 换句话说,闭包允许一个函数访问并操作函数外部的变量。 闭包的核心特性: 函数内部可以访问外部函数的变量即使外部函数已经返回,内部…

一款新开源跨平台的.NET Word(docx)模版导出引擎,完美支持Linux和Mac操作系统(附源码)

前言 在数字化办公日益盛行的今天,文档处理成为了我们日常工作不可或缺的一部分。然而,许多传统的文档处理工具都依赖于特定的操作系统和复杂的组件安装,这无疑给跨平台办公带来了诸多不便。为了解决这一问题,我们找到了一个新的…

【MR开发】在Pico设备上接入MRTK3(一)——在Unity工程中导入MRTK3依赖

写在前面的话 在Pico上接入MRTK3,目前已有大佬开源。 https://github.com/Phantomxm2021/PicoMRTK3 也有值得推荐的文章。 MRTK3在PICO4上的使用小结 但由于在MacOS上使用MRTK3,无法通过Mixed Reality Feature Tool工具管理MRTK3安装包。 故记录一下…

◇【论文_20151120_20160405v3】Dueling Network 决斗〔Google DeepMind〕

整理代码:Dueling_DQN__Pendulum_v1.ipynb https://arxiv.org/abs/1511.06581 Dueling Network Architectures for Deep Reinforcement Learning 文章目录 摘要1. 引言1.1. 相关工作 2. 背景2.1. Deep Q-networks 【DQN】2.2. Double Deep Q-networks 【DDQN】2.3…

OpenCV高级图形用户界面(13)选择图像中的一个矩形区域的函数selectROI()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 允许用户在给定的图像上选择一个感兴趣区域(ROI)。 该功能创建一个窗口,并允许用户使用鼠标来选择一个 ROI。…

其他css的用途

1.animation-fill-mode: backwards; //避免了在动画开始前元素的突然显现,动画必要。 2.用rem响应式字体大小,可以在html样式定义font-size?(例10px,62.5%(100%是16px))。然后样式就可以用rem代替px。 3.color: transparent;: 这行代码将文…

计算生物学与生物信息学漫谈-2-测序深度/读长质量和Fasta处理

上一篇文章中我们介绍了测序技术的由来与发展,那么在介绍第三代测序的时候,我们提到了关于测序深度和读长的问题,那么本篇文章就详解介绍一下。 计算生物学与生物信息学漫谈-1-测序一路走来-CSDN博客 目录 1.测序深度SEQUENCING DEPTH &…

《AI生成式工具使用》之:自助生成视频

目录 背景说明及目标: 实现过程: 1、有问题找度娘 2、利用剪映AI生成视频具体步骤 剪映AI感受 3、利用万彩AI生成视频具体步骤 万彩AI感受 4、利用腾讯云剪生成视频具体步骤 腾讯云剪感受 最终结论: 关注我,躺不平就一起…

【部署篇】RabbitMq-02单机模式部署

RabbitMQ和Erlang/OTP兼容性矩阵 下表提供了当前支持的RabbitMQ版本系列的Erlang兼容性矩阵。更多RabbitMQ版本,请参阅官网的系列兼容性列表。官网地址:https://www.rabbitmq.com/docs/which-erlang RabbitMQ版本最小支持版本最大支持版本备注 4.0.24.…

Axure重要元件三——中继器添加数据

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 本节课:中继器添加数据 课程内容:添加数据项、自动添加序号、自动添加数据汇总 应用场景:表单数据的添加 案例展示: 步骤…

经验是最坏的老师

奥斯卡.王尔德说过:经验是最坏的老师。他经常先考试,然后再给出指导。 这让我想起了另外一句话:愚笨的人,往往都在犯同样的错误;普通的人,从自己的错误中学习;聪明人从别人的错误中学习。 如果…

Linux 防火墙的开启、关闭、禁用命令

Linux 防火墙的开启、关闭、禁用命令 文章目录 Linux 防火墙的开启、关闭、禁用命令1.设置开机启用防火墙2.设置开机禁用防火墙3.启动防火墙4.关闭防火墙5.检查防火墙状态 1.设置开机启用防火墙 systemctl enable firewalld.service2.设置开机禁用防火墙 systemctl disable f…