static关键字-内存图解

C语言 static 关键字深度解析:3种用法与内存布局实战图解 我曾经在一个内存只有32KB的嵌入式项目中,通过将几个大型查找表改为static const,节省了近5KB的栈空间,这相当于系统总内存的15%以上。这种优化之所以有效,是因为static const数据被放置在只读段,不需要运行时初始化,同时避免了栈上的临时拷贝。关键字就像一颗低调却功能强大的恒星,它默默影响着变量的生命周期、函数的作用域,甚至程序的整体架构。将模块内部实现细节函数声明为static,只暴露必要的接口函数,可以创建更安全、更易维护的代码结构。的底层机制,是迈向高级编程的必经之路。 阅读详情
以下面的例子为例说明
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package cn.galc.test;
 
public class Cat {
 
   /**
    * 静态成员变量
    */
   private static int sid = 0 ;
 
   private String name;
 
   int id;
 
   Cat(String name) {
     this .name = name;
     id = sid++;
   }
 
   public void info() {
     System.out.println( "My Name is " + name + ",NO." + id);
   }
 
   public static void main(String[] args) {
     Cat.sid = 100 ;
     Cat mimi = new Cat( "mimi" );
     Cat pipi = new Cat( "pipi" );
     mimi.info();
     pipi.info();
   }
}

通过画内存分析图了解整个程序的执行过程

  执行程序的第一句话:Cat.sid = 100;时,这里的sid是一个静态成员变量,静态变量存放在数据区(方法区)(data seg),所以首先在数据区里面分配一小块空间sid,第一句话执行完后,sid里面装着一个值就是100。

  此时的内存布局示意图如下所示

2015103085457947.png (497×296)

接下来程序执行到:

?
1
Cat mimi = new Cat(“mimi”);

  这里,调用Cat类的构造方法Cat(String name),构造方法的定义如下:

?
1
2
3
4
5
6
7
Cat ( String name){
 
   this .name = name;
 
  id=sid++;
 
}

  调用时首先在栈内存里面分配一小块内存mm,里面装着可以找到在堆内存里面的Cat类的实例对象的地址,mm就是堆内存里面Cat类对象的引用对象。这个构造方法声明有字符串类型的形参变量,所以这里把“mimi”作为实参传递到构造方法里面,由于字符串常量是分配在数据区存储的,所以数据区里面多了一小块内存用来存储字符串“mimi”。此时的内存分布如下图所示:

2015103085520724.png (500×298)

当调用构造方法时,首先在栈内存里面给形参name分配一小块空间,名字叫name,接下来把”mimi”这个字符串作为实参传递给name,字符串也是一种引用类型,除了那四类8种基础数据类型之外,其他所有的都是引用类型,所以可以认为字符串也是一个对象。所以这里相当于把”mimi”这个对象的引用传递给了name,所以现在name指向的是”mimi”。所以此时内存的布局如下图所示:

2015103085536595.png (498×296)

接下来执行构造方法体里面的代码:

?
1
this .name=name;

  这里的this指的是当前的对象,指的是堆内存里面的那只猫。这里把栈里面的name里面装着的值传递给堆内存里面的cat对象的name属性,所以此时这个name里面装着的值也是可以找到位于数据区里面的字符串对象“mimi”的,此时这个name也是字符串对象“mimi”的一个引用对象,通过它的属性值就可以找到位于数据区里面的字符串对象“mimi”。此时的内存分布如下图所示:

2015103085553096.png (497×297)

接下来执行方法体内的另一句代码:

?
1
id=sid++;

  这里是把sid的值传递给id,所以id的值是100,sid传递完以后,自己再加1,此时sid变成了101。此时的内存布局如下图所示。

2015103085614750.png (497×297)

 到此,构造方法调用完毕,给这个构造方法分配的局部变量所占的内存空间全部都要消失,所以位于栈空间里面的name这块内存消失了。栈内存里面指向数据区里面的字符串对象“mimi”的引用也消失了,此时只剩下堆内存里面的指向字符串对象“mimi”的引用没有消失。此时的内存布局如下图所示:

2015103085633187.png (497×296)

接下来执行:

?
1
Cat pipi = new Cat(“pipi”);

  这里是第二次调用构造方法Cat(),整个调用过程与第一次一样,调用结束后,此时的内存布局如下图所示:

2015103085650357.png (498×297)

最后两句代码是调用info()方法打印出来,打印结果如下:

  

  通过这个程序,看出来了这个静态成员变量sid的作用,它可以计数。每当有一只猫new出来的时候,就给它记一个数。让它自己往上加1。

  程序执行完后,内存中的整个布局就如上图所示了。一直持续到main方法调用完成的前一刻。

  这里调用构造方法Cat(String name) 创建出两只猫,首先在栈内存里面分配两小块空间mimi和pipi,里面分别装着可以找到这两只猫的地址,mimi和pipi对应着堆内存里面的两只猫的引用。这里的构造方法声明有字符串类型的变量,字符串常量是分配在数据区里面的,所以这里会把传过来的字符串mimi和pipi都存储到数据区里面。所以数据区里面分配有存储字符串mimi和pipi的两小块内存,里面装着字符串“mimi”和“pipi”,字符串也是引用类型,除了那四类8种的基础数据类型之外,其他所有的数据类型都是引用类型。所以可以认为字符串也是一个对象。

  这里是new了两只猫出来,这两只猫都有自己的id和name属性,所以这里的id和name都是非静态成员变量,即没有static修饰。所以每new出一只新猫,这只新猫都有属于它自己的id和name,即非静态成员变量id和name是每一个对象都有单独的一份。但对于静态成员变量来说,只有一份,不管new了多少个对象,哪怕不new对象,静态成员变量在数据区也会保留一份。如这里的sid一样,sid存放在数据区,无论new出来了多少只猫在堆内存里面,sid都只有一份,只在数据区保留一份。

  静态成员变量是属于整个类的,它不属于专门的某个对象。那么如何访问这个静态成员变量的值呢?首先第一点,任何一个对象都可以访问这个静态的值,访问的时候访问的都是同一块内存。第二点,即便是没有对象也可以访问这个静态的值,通过“类名.静态成员变量名”来访问这个静态的值,所以以后看到某一个类名加上“.”再加上后面有一个东西,那么后面这个东西一定是静态的,如”System.out”,这里就是通过类名(System类)再加上“.”来访问这个out的,所以这个out一定是静态的。
如果一个类成员被声明为static,它就能够在类的任何对象创建之前被访问,而不必引用任何对象。static 成员的最常见的例子是main( ) 。因为在程序开始执行时必须调用main() ,所以它被声明为static。
声明为static的变量实质上就是全局变量。当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量,例如:声明一个static的变量count作为new一个类实例的计数。声明为static的方法有以下几条限制:
(1)、它们仅能调用其他的static 方法。
(2)、它们只能访问static数据。
(3)、它们不能以任何方式引用this 或super。
如果你需要通过计算来初始化你的static变量,你可以声明一个static块,Static 块仅在该类被加载时执行一次。下面的例子显示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
的类有一个 static 方法,一些 static 变量,以及一个 static 初始化块:
public class UserStatic {
     static int a = 3 ;
     static int b; 
     static void meth( int x) {
       System.out.println( "x = " + x);
       System.out.println( "a = " + a);
       System.out.println( "b = " + b); 
     } 
     static {
       System.out.println( "Static block initialized." );
       b = a * 4 ; 
     } 
     public static void main(String args[]) {
       meth( 42 ); 
     }
   }

一旦UseStatic 类被装载,所有的static语句被运行。首先,a被设置为3,接着static 块执行(打印一条消息),最后,b被初始化为a*4 或12。然后调用main(),main() 调用meth() ,把值42传递给x。3个println ( ) 语句引用两个static变量a和b,以及局部变量x 。
注意:在一个static 方法中引用任何实例变量都是非法的。
下面是该程序的输出:

?
1
2
3
4
Static block initialized.
x = 42
a = 3
b = 12

在定义它们的类的外面,static 方法和变量能独立于任何对象而被使用。这样,你只要在类的名字后面加点号(.)运算符即可。例如,如果你希望从类外面调用一个static方法,你可以使用下面通用的格式:
classname.method( )
这里,classname 是类的名字,在该类中定义static方法。可以看到,这种格式与通过对象引用变量调用非static方法的格式类似。一个static变量可以以同样的格式来访问——类名加点号运算符。这就是Java 如何实现全局功能和全局变量的一个控制版本。
总结:
(1)、如果不加static修饰的成员是对象成员,也就是归每个对象所有的。
(2)、加static修饰的成员是类成员,就是可以由一个类直接调用,为所有对象共有的。
 
 
Java Static:作为修饰符, 可以用来修饰变量、方法、代码块(但绝对不能修饰类)。

(1)、修饰变量:
类的所有对象共同拥有的一个属性,也称为类变量。这类似于C语言中的全局变量。类变量在类加载的时候初始化,而且只被初始化一次。在程序中任何对象对静态变量做修改,其他对象看到的是修改后的值。因此类变量可以用作计数器。另外,Java Static变量可以用类名直接访问,而不必需要对象。
(2)、修饰方法:
类的所有对象共同拥有的一个功能,称为静态方法。静态方法也可以用类名直接访问,而不必需要对象。所以在静态方法里不能直接访问非静态变量和非静态方法,在Static方法里不能出现this或者super等关键字。
(3)、修饰Java代码块:
用static去修饰类里面的一个独立的代码块,称为静态代码块。静态代码块在类第一次被加载的时候执行,而且只执行一次。静态代码块没有名字,因此不能显式调用,而只有在类加载的时候由虚拟机来调用。它主要用来完成一些初始化操作。
(4)、说说类加载:
JVM在第一次使用一个类时,会到classpath所指定的路径里去找这个类所对应的字节码文件, 并读进JVM保存起来,这个过程称之为类加载。
可见,无论是变量,方法,还是代码块,只要用static修饰,就是在类被加载时就已经"准备好了",也就是可以被使用或者已经被执行。都可以脱离对象而执行。反之,如果没有static,则必须通过对象来访问。

java中带static关键字的程序内存分析 想要下载此文件,请先下载本人“java程序中的内存分配问题”,因为那个例子比较简单而且分析详细透彻,可以使你更容易理解,如果你对java程序执行过程中的内存分配有一定的了解,可以直接下载本文件 立即下载

相关推荐

dify离线部署

以bge-m3为例,本地部署bge-m3首先在一台能连网的linux服务器上(部署有ollama)创建想要保存模型的文件夹编辑ollama.service,配置ollama模型的保存路径添加模型存储地址将models目录设置属主,必须做,否则ollama无法启动重新加载配置文件并重启ollama测试ollama 运行是否正常最后拉取 bge-m3可在/opt/LLMModels/bge_m3/models目录下看到拉取得模型使用tar命令压缩文件夹。

weixin_42538734的博客 3069

深入理解Java虚拟机第二章

1、Jvm内存布局 (1)程序计数器:线程私有,可以看作是当前线程所执行的字节码的行号指示器。 分支、 循环、 跳转、 异常处理、 线程恢复等基础功能都需要依赖这个计数器来完成。 (2)虚拟机栈:线程私有,每个方法被执行的时候, Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。 (3)本地方法栈:线程私有, 与虚拟机栈所发挥的作用是非常相似的, 其区别只是虚拟机栈为虚拟机执行Java

qq_43357821的博客 259

基于QT的华为网络摄像头二次开发

第一次使用华为的网络摄像头并进行二次开发,网上关于QT对华为网络摄像头的二次开发的文章很少,基于项目的需求做了一些工作,特此记录。 目标: 1、实时预览 2、手动控制录制视频 3、监听告警型号 4、实时获取元数据中的划定区域内的人数 摄像头型号如下: 准备工作: 在购买摄像头后,应当在官网下载对应的开发资料,如果需要权限,则联系华为的技术支持人员。下载资料如下: SDC Development Kit Demo 8.0.T9 SDK DEMO下载地址:https://bbs.hua

xumingyifrend的博客 3169

static修饰的对象在内存中的存储及其用法

static成员在内存中的存储、static的用法、static成员被初始化的问题

qq_50309255的博客 2018

【机电杂谈2】BLDC和PMSM的特点和区别

在日常生活中,小到电动玩具,大到电动汽车,永磁电机的身影可以说是无处不在。有刷直流电机、无刷直流电机、永磁同步电机由于其结构和输出特定的不同也被应用到不同的场合。如果你经常拆一些玩具和家电,就会看到大量的有刷直流电机和无刷直流电机,而永磁同步电机主要应用在高精度的工业伺服和电动汽车领域。本文就从电机的结构和控制方面,对这几种常见的永磁电机做简单的梳理和归纳。

2936

不只是驱动:拆解AIC8800 WiFi模组在RK Android系统的完整启动链(从DTS到HAL)

本文深入解析了AIC8800 WiFi模组在RK Android系统中的完整启动链,从设备树(DTS)配置到HAL层适配,涵盖驱动移植、固件加载及用户空间服务协同等关键环节。通过详细的技术分析和调试技巧,帮助开发者解决RK平台与AIC8800模组的兼容性问题,优化WiFi子系统性能。

weixin_30439067的博客 492

static 关键字详细总结

static 的作用

m0_56910081的博客 4281

从零到一:RF-DETR如何通过神经架构搜索重塑实时目标检测的边界

RF-DETR通过创新的权重共享神经架构搜索(NAS)机制,重新定义了实时目标检测的技术边界。这项技术在COCO等基准测试中表现卓越,成为首个AP超过60的实时检测器,同时保持跨领域稳定性和高效推理速度。RF-DETR的动态架构调整能力使其能够适应从嵌入式设备到云端服务器的各种硬件环境,为工业质检、自动驾驶等场景提供灵活解决方案。

weixin_29061531的博客 469

static关键字以及内存分析

此文为网上资源收集而写。 今天我们来看一下static关键字 static表示全局或静态的意思,用来修饰成员变量或者成员方法,也可以形成static代码块,但是在java语言中其实是没有所谓全局变量的概念的。  被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说,它不依赖类特定的实例,被类的所有实例共享。只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内

BryantLmm的博客 669

RoCE Overlay

1. RoCE over vxlan 配置vxlan封装的RoCE流量,可以在PF switchdev模式下利用ovs bridge,或直接设置tc rules。下面将基于一对NIC互联的服务器介绍两种方式的使用,并分析封装后的数据包结构。 1.1. 基本配置 - VF与switchdev 首先创建VF,并为两个host设置PF的switchdev模式。使用ovs bridge或tc rules,...

sunshuying1010的博客 3063

电动汽车远程监控与诊断软件:BMW ConnectedDrive EV远程监控二次开发_7.数据安全与隐私保护

数据加密是保护数据安全的重要手段之一。在电动汽车远程监控与诊断软件中,加密技术可以确保数据在传输过程中的安全性和完整性。常见的加密技术包括对称加密和非对称加密。

zhubeibei168的博客 884

【static】---- 关键字在内存--图解

Static 关键字在内存中的图解: 源码: //写一个人类 class Person {       private String name;       private int age;       static String country="CN";             public Person(String name,int age)       {

2002

moveit——基于octomap的碰撞检测

机械臂对棚顶进行碰撞检测。

如果想成为中心,那么就到中心去吧。 1355

java static 内存_Java中this、static关键字的内存图解

Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break double implements private this byte else import protected throw throws case extends instanc...

weixin_39840733的博客 267

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

static关键字、类的分类、对象的内存图解

目录 static关键字 类的分类 对象的内存图解 static关键字 成员变量+static=静态变量 主要是解决成员变量重复的问题 class Chinese{ static int momo; static boolean kaka; String name; String age; static String c...

qq_43410906的博客 228

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

java的Static关键字使用内存图解:

Static内存图解:

LFSenior 2687

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

深入内存图解static关键字,C站最详细

static修饰的一切,都与对象无关,和类有关 一.static修饰的属性 (一).static 修饰的属性 1.存储在JVM的哪个区 static修饰的属性属于类属性,存在于JVM的方法区,所有对象共享此属性。没有使用static修饰的属性属于对象属性,存在与堆内 public class Person{ static int age = 18; int id ; String name; public void show(){ }

qq_52655865的博客 1204

Java中this、static关键字的内存图解

Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break double implements private this byte else import protected throw throws case extends ...

weixin_30500105的博客 120

java this内存图_Java中this、static关键字的内存图解

Java中的关键字有很多,abstract default goto* null switch boolean do if package nchronzed break double implements private this byte else import protected throw throws case extends instanc...

weixin_28744573的博客 261

java基础--static关键字的使用以及内存图解

1、静态变量--每当创建一个类的实例时就会在堆区创建这个类的所有属性对象,如有被static 修饰的属性时,则将此属性放入静态区中被共享。 1-1未加static关键字修饰的变量 /** * static关键字修饰的变量 * @author Administrator * */ public class Test_Static { public static void main(St

qq_28743891的博客 317

从JVM内存模型出发,图解Java static关键字的加载时机与使用陷阱

本文深入解析Java中static关键字的加载时机与使用陷阱,从JVM内存模型出发,详细介绍了静态变量在方法区的存储位置、类加载机制中的初始化过程,以及多线程环境下的线程安全问题。通过图解和实例分析,帮助开发者避免常见的static使用误区,提升代码质量与性能。

weixin_42666036的博客 227

《java入门第一季》之面向对象(static关键字内存图解)

态度决定高度A=X+Y+Z 453

static关键字

static关键字 static关键字的特点 static静态的,可以修饰成员变量,也可以修饰成员方法。 修饰成员变量,此变量为共享变量,被这个类的所有对象所共享。如果某个成员变量是被所有对象共享的,那么它就应该定义为静态的。 被静态所修饰的成员,是随着类的加载而加载,优先于对象存在。 被静态所修饰的成员属于类,推荐使用类名调用。当然你可以使用对象名,但是不推荐。 静态修饰的内容一般我们称其为:与类相关的,类成员 static的内存图解 static的注意事项 在静态方法中是没有this关键字的 静态是

weixin_45678691的博客 116

java中Static内存图解

Static内存图解: 解析: 如代码: ①:当程序运行,class进行加载这时在方法区则会有class文件区 而class文件区内又有两个区(代码中有两个类一个person一个personDemo)这时class文件区的第一个区产生: 然后产生第二个区 class区域内有成员属性与成员方法.而为什么没有静态的属性与方法呢,是因为当程序加载该class文件时,系统会自动的把他所有静态的属性与方法分配到静态区 (方法区内有一个静态区);静态区内也有两块区域一个是personDemo类标记的main(S

qq_30864125的博客 673

【static】----static关键字--内存中简单过程

Static关键字 静态修饰符在内存中的简单图解过程 源代码: //static静态的测试 //写一个Person()类 class Person { String name; static String country="China"; public void show() { System.out.println("country:"+country+",name:"

811
上一篇: Eclipse快捷键
下一篇: 内存分配及变量存储位置(堆、栈、方法区常量池、方法区静态区)
billion_Fu
博客等级 码龄9年 3粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值