第07天 Static关键字作用及用法

每天学习一个知识点

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉
🍎个人主页:Leo的博客
💞当前专栏:每天一个知识点
✨特色专栏: MySQL学习
🥭本文内容:第07天 Static关键字作用及用法
🖥️个人小站 :个人博客,欢迎大家访问
📚个人知识库: 知识库,欢迎大家访问

1. 概述

Static是静态修饰符,什么叫静态修饰符呢?大家都知道,在程序中任何变量或者代码都是在编译时由系统自动分配内存来存储的,而所谓静态就是指在编译后所分配的内存会一直存在,直到程序退出内存才会释放这个空间,也就是只要程序在运行,那么这块内存就会一直存在。这样做有什么意义呢?在Java程序里面,所有的东西都是对象,而对象的抽象就是类,对于一个类而言,如果要使用他的成员,那么普通情况下必须先实例化对象后,通过对象的引用才能够访问这些成员,但是用static修饰的成员可以通过类名加“.”进行直接访问。

官方解释静态变量Static Variable)在计算机编程领域指在程序执行前系统就为之静态分配(也即在运行时中不再改变分配情况)存储空间的一类变量。与之相对应的是在运行时只暂时存在的自动变量(即局部变量)与以动态分配方式获取存储空间的一些对象,其中自动变量的存储空间在调用栈上分配与释放。(选自维基百科)

如何理解?为什么要这样做?例子?

  • 解释:

首先,先了解一下Java的内存分配:

Java 把内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用,堆内存主要存放一些对象。

什么是句柄: 自己理解的话,其实就是类似于对这些静态的成员进行编号。

那为什么要这样做呢?

在 JVM 加载一个类的时候,若该类存在 static 修饰的成员变量和成员方法,则会为这些成员变量和成员方法在固定的位置开辟一个固定大小的内存区域,有了这些“固定”的特性,那么 JVM 就可以非常方便地访问他们。同时如果静态的成员变量和成员方法不出作用域的话,它们的句柄都会保持不变。同时 static 所蕴含“静态”的概念表示着它是不可恢复的,即在那个地方,你修改了,他是不会变回原样的,你清理了,他就不会回来了。

可能这些有些偏于理论,下面我们通过一些代码示例来进一步了解Static关键字

2. 修饰成员属性

当我们需要在一个类(class)中定义一个属性为公共的属性,就好比说我们需要这个属性是所有类都是共有的,并且这个属性的值是同一个。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:06* @description :*/
class Book{// 设置一个默认的值static String pub = "清华大学出版社";// 用来和 static 作为对比String description = "描述";// Book 类正常的属性private String title;private double price;// Book 的构造类public Book(String title, double price) {this.title = title;this.price = price;}// 获取 Book 的信息public void getInfo(){System.out.println("图书名称:"+ this.title + ",价格为:"+ this.price + ",出版社为:"+ pub + ",描述 "+ this.description);}
}public class Test {public static void main(String[] args) {// 实例化三个Book类Book book1 = new Book("Android开发实战", 69.8);Book book2 = new Book("Java EE开发实战", 49.8);Book book3 = new Book("Java 开发教程", 79.8);// 在没有设置 pub 属性的情况下输出book1.getInfo();book2.getInfo();book3.getInfo();System.out.println("————————————————————无敌分割线————————————————————");// 我们给 book1 设置一个 pub 属性Book.pub = "中信出版社";book1.description = "这本书很牛逼,看了你就知道";book1.getInfo();book2.getInfo();book3.getInfo();}
}

控制台输出

image-20230818111309548

从控制台输出的结果,可以看到:

  • 如果给 属性 赋默认值,在上面的例子中是(description 和 pub),输出的结果为都是默认的。
  • 当我们修改了类中 static 关键字声明的属性,那么只要修改了一次,那么其他所有的对象的这个属性都给修改了。

通过类调用 static 声明的属性

但是基于上面的代码,我们发现如果是其中的一个类对象就改变了所有的对象的属性,这样子操作是不是感觉不是特别好?然后在Java中,如果是使用 static 声明的属性值,是可以直接通过类调用的。

public class Test {public static void main(String[] args) {// 实例化三个Book类Book book1 = new Book("Android开发实战", 69.8);Book book2 = new Book("Java EE开发实战", 49.8);Book book3 = new Book("Java 开发教程", 79.8);// 在没有设置 pub 属性的情况下输出book1.getInfo();book2.getInfo();book3.getInfo();System.out.println("————————————————————无敌分割线————————————————————");// 我们使用 Book 类直接调用pubBook.pub = "中信出版社";book1.description = "这本书很牛逼,看了你就知道";book1.getInfo();book2.getInfo();book3.getInfo();}
}

没有实例化类时,调用 static 属性

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:19* @description :*/
class Book2{// 设置一个默认的值static String pub = "清华大学出版社";// 用来和 static 作为对比String description = "描述";// Book 类正常的属性private String title;private double price;// Book 的构造类public Book2(String title, double price) {this.title = title;this.price = price;}// 获取 Book 的信息public void getInfo(){System.out.println("图书名称:"+ this.title + ",价格为:"+ this.price + ",出版社为:"+ pub + ",描述 "+ this.description);}
}public class Test3 {public static void main(String[] args) {// 在没有实例化对象时,就调用System.out.println(Book.pub);// 没事实例化对象的时候,去给static属性赋值上默认值Book2.pub = "北京大学出版社";System.out.println(Book.pub);// 新建一个类,输入 pub 属性Book2 book = new Book2("Java", 88);book.getInfo();}
}

控制台输出

image-20230818112054747

由此,我们看出,在没有实例化对象的时候,就可以直接通过类去掉用 static属性,并且还可以修改 static 的属性。static 属性声明虽然是在类的结构中,但是并不受到对象的控制,是独立存在的。

static 属性与非 static 属性的区别

  • static 声明的属性和普通属性(非 static 属性)最大的区别在于保存的内存区域不同。static 所修饰的在静态数据区。而不是在堆和栈。

  • static 属性与非 static 属性还有一个最大的区别,就是在于所有非 static 属性必须产生实例化之后才可以访问,但是static 属性不受实例化对象的控制。也就是说,在没有产生实例化对象的情况下,依然可以使用 static 对象。

3. 修饰成员方法

说明

方法本来就是存放在类的定义当中的。static修饰成员方法的作用是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:19* @description :*/
class Test2{public static void sayHello(String name) {System.out.println("Hello," + name);}
}public class Demo {public static void main(String[] args) {Test2.sayHello("Leo");}
}

控制台输出

image-20230818112801463

4. 修饰代码块

说明

**static **{ }就是静态块,当类加载器载入类的时候,这一部分代码被执行,常用于对静态变量进行初始化工作。当其他代码用到这个类,类加载器才会将它载入。

代码只能执行一次,不能再调用。在静态块中,可以访问静态变量,调用静态方法。

如果去掉static,{ }中的代码则会在创建类对象的时候才执行,(相当于把这部分代码复制到各个构造函数中),这样可以实现块中的内容在多个构造函数中的复用。

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:29* @description :*/
class Test4{static {System.out.println("静态代码块执行");}{System.out.println("普通代码块执行");}public Test4(){System.out.println("This is Test()");}public Test4(String string){System.out.println("This is Test(String string)");}
}public class Demo2 {public static void main(String[] args) {System.out.println("------------------------");Test4 test1 = new Test4();System.out.println("------------------------");Test4 test2 = new Test4("Hello");}
}

控制台输出

image-20230818113217885

5. 修饰内部类

static 不能修饰普通类,但可以修饰内部类。原因如下:

static 修饰的东西被我们成为类成员,它会随着类的加载而加载,比如:静态代码块,静态成员,静态方法(这里只是加载,并没有调用)等等。若把一个Class文件中的外部类设为static,那目的何在呢?难道让这个类随着应用的启动而加载吗?如果我在这次使用过程中根本没有使用过这个类,那么是不是就会浪费内存。这样来说设计不合理,总而言之,设计不合理的地方,Java是不会让它存在的。

为什么内部类可以使用 static 修饰呢,因为内部类算是类的成员了,如果我们没有使用静态来修饰,那么我们在创建内部类的时候就需要先有一个外部类的对象,如果我们一直在使用内部类,那么内存中就会一直存在外部类的引用,而我们有时候只需要使用内部类,不需要外部类,那么还是会浪费内存,甚至会造成内存溢出。使用 static修饰内部类之后,内部类在创建对象时就不需要有外部类对象的引用了。

package com.cisyam.testStatic;public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton (){}public static final Singleton getInstance() {return SingletonHolder.INSTANCE;}
}class Demo3 {public static void main(String[] args) {Singleton singleton = Singleton.getInstance();System.out.println(singleton);}}

6. static加载顺序

首先思考,下边程序是否能编译通过?若可以编译通过,那么执行结果是什么?

package com.cisyam.testStatic;/*** @author : Leo* @version 1.0* @date 2023/8/18 11:38* @description :*/
public class User {private static String name;public void setName(String name) {this.name = name;}public static String getName() {return User.name;}
}
public class Test6 {public static void main(String[] args) {User user = new User();user.setName("Leo");System.out.println("user = " + User.getName());}
}

控制台输出

image-20230818114056989

从上述结果可见,实例对象可以访问访问类变量。

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

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

相关文章

Kubernetes网络组件详解

目录 1、Kubernetes网络组件 1.1、Flannel网络组件 1.2、Calico 网络插件 2、环境准备 2.2、部署docker环境 3、部署kubernetes集群 3.1、组件介绍 3.2、配置阿里云yum源 3.3、安装kubelet kubeadm kubectl 3.4、配置init-config.yaml 3.5、安装master节点 3.6、安…

MySQL高可用MHA

目录 前言 一、概述 二、配置免密、组从复制 三、MHA配置 四、测试 总结 前言 MySQL高可用管理工具(MHA,Master High Availability)是一个用于自动管理MySQL主从复制的工具,它可以提供高可用性和自动故障转移。MHA由原版的MHA工具…

web前端tips:js继承——组合继承

上篇文章给大家分享了 js继承中的借用构造函数继承 web前端tips:js继承——借用构造函数继承 在借用构造函数继承中,我提到了它的缺点 无法继承父类原型链上的方法和属性,只能继承父类构造函数中的属性和方法 父类的方法无法复用&#xff0…

【算法】双指针划分思想妙解移动零

Problem: 283. 移动零 文章目录 思路算法图解分析复杂度Code 思路 首先我们来讲一下本题的思路 本题主要可以归到【数组划分/数组分块】这一类的题型。我们将一个数组中的所有元素划分为两段区间,左侧是非零元素,右侧是零元素 那解决这一类的题我们首先想…

蓝帽杯 取证2022

网站取证 网站取证_1 下载附件 并解压 得到了一个文件以及一个压缩包 解压压缩包 用火绒查病毒 发现后门 打开文件路径之后 发现了一句话木马 解出flag 网站取证_2 让找数据库链接的明文密码 打开www文件找找 查看数据库配置文件/application/database.php(CodeI…

【网络】网络层——IP协议

🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言:你只管努力,剩下的交给时间! 网络层中,IP协议首部和有效载荷组成的完整数据称为数据报。 IP协议 🍉TCP和IP的…

网络安全 Day31-运维安全项目-容器架构下

容器架构下 6. Dockerfile6.1 Docker自动化DIY镜像之Dockerfile1) 环境准备2) 书写Dockerfile内容3) 运行Dockerfile生成镜像4) 运行容器5) 小结 6.2 案例14:Dockerfile-RUN指令1) 书写Dockerfile2) 构建镜像3) 启动容器4) 测试结果 6.3 Dockerfile指令 …

解决生成式AI落地之困,亚马逊云科技提供完整解决方案

生成式AI技术无疑是当前最大的时代想象力之一。 资本、创业者、普通人都在涌入生成式AI里去一探究竟:“百模大战”连夜打响,融资规模连创新高,各种消费类产品概念不断涌现……根据Bloomberg Intelligence 的报告,2022年生成式AI 市…

LeetCode--HOT100题(31)

目录 题目描述:25. K 个一组翻转链表(困难)题目接口解题思路代码 PS: 题目描述:25. K 个一组翻转链表(困难) 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表…

如何避免爬虫IP被屏蔽

各位爬友们好,作为一名专业的爬虫代理提供者,我要和大家分享一些避免爬虫IP被屏蔽的实用技巧。你知道吗,当我们爬取数据的时候,很容易被目标网站识别出来并封禁我们的IP地址,导致无法继续爬取数据。这个问题困扰了很多…

邀请函|澎峰科技邀您参加CCF HPC China2023

一年一度的全球超算盛会! 以“算力互联智领未来”为主题的第十九届全国高性能计算学术年会(CCF HPC China 2023)将于8月24-26日(展览23-25日)在青岛红岛国际会议展览中心举办。 九大院士领衔 打造顶级超算盛会 力邀…

【前端|Javascript第5篇】全网最详细的JS的内置对象文章!

前言 在当今数字时代,前端技术正日益成为塑造用户体验的关键。我们在开发中需要用到很多js的内置对象的一些属性来帮助我们更快速的进行开发。或许你是刚踏入前端领域的小白,或者是希望深入了解内置对象的开发者,不论你的经验如何&#xff0c…

Linux:shell脚本:基础使用(4)《正则表达式-grep工具》

正则表达式定义: 使用单个字符串来描述,匹配一系列符合某个句法规则的字符串 正则表达式的组成: 普通字符串: 大小写字母,数字,标点符号及一些其他符号 元字符:在正则表达式中具有特殊意义的专用字符 正则表…

OpenCV-Python中的图像处理-图像特征

OpenCV-Python中的图像处理-图像特征 图像特征Harris角点检测亚像素级精度的角点检测Shi-Tomasi角点检测SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features)FAST算法BRIEF(Binary Robust Independent Elementary Features)算法ORB (Oriented FAST and R…

中睿天下受邀参加第六届电力信息通信新技术大会并发表主题演讲

2023年8月9-11日,中国电力企业联合会科技开发服务中心以“加快数字化转型助力新型电力系统建设”为主题,在杭州举办2023年(第六届)电力信息通信新技术大会暨数字化发展论坛。 大会旨在加快推进“双碳”目标下的新型能源体系和新型…

无公网IP,公网SSH远程访问家中的树莓派教程

文章目录 前言 如何通过 SSH 连接到树莓派步骤1. 在 Raspberry Pi 上启用 SSH步骤2. 查找树莓派的 IP 地址步骤3. SSH 到你的树莓派步骤 4. 在任何地点访问家中的树莓派4.1 安装 Cpolar内网穿透4.2 cpolar进行token认证4.3 配置cpolar服务开机自启动4.4 查看映射到公网的隧道地…

JVM——类文件结构

文章目录 一 概述二 Class 文件结构总结2.1 魔数2.2 Class 文件版本2.3 常量池2.4 访问标志2.5 当前类索引,父类索引与接口索引集合2.6 字段表集合2.7 方法表集合2.8 属性表集合 一 概述 在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class …

【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

文章目录 1、字典学习与稀疏编码2、sklearn的实现3、示例 1、字典学习与稀疏编码 简单来说,稀疏编码就是把输入向量(信号)/ 矩阵(图像)表示为稀疏的系数向量和一组超完备基向量(字典)的线性组合…

java-垃圾回收与算法

垃圾回收与算法 1. 如何确定垃圾 1. 引用计数法 在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用&…

Grounding dino + segment anything + stable diffusion 实现图片编辑

目录 总体介绍总体流程 模块介绍目标检测: grounding dino目标分割:Segment Anything Model (SAM)整体思路模型结构:数据引擎 图片绘制 集成样例 其他问题附录 总体介绍 总体流程 本方案用到了三个步骤,按顺序依次为&#xff1a…