版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/m0_37700275/article/details/88556697
目录介绍
- 01.static的作用
- 02.static变量存储位置
- 03.用static静态变量潜在性问题
- 04.静态变量的生命周期
- 05.静态变量何时销毁
- 06.静态引用的对象回收
- 07.静态方法变量内存图
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
01.static的作用
- 可以用来修饰:成员变量,成员方法,代码块,内部类等。具体如下所示
- 修饰成员变量和成员方法
- 被 static 修饰的成员属于类,不属于单个这个类的某个对象,被类中所有对象共享,可以并且建议通过类名调用。
- 被static 声明的成员变量属于静态成员变量,静态变量存放在Java内存区域的方法区。
- 静态代码块
- 静态代码块定义在类中方法外,静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)
- 该类不管创建多少对象,静态代码块只执行一次.
- 静态内部类(static修饰类的话只能修饰内部类)
- 静态内部类与非静态内部类之间存在一个最大的区别:
- 非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:1.它的创建是不需要依赖外围类的创建。2.它不能使用任何外围类的非static成员变量和方法。
- 静态导包(用来导入类中的静态资源,1.5之后的新特性):
- 这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。
- 修饰成员变量和成员方法
02.static变量存储位置
- static变量存储位置
- 注意是:存储在JVM的方法区中
- static变量在类加载时被初始化,存储在JVM的方法区中,整个内存中只有一个static变量的拷贝,可以使用类名直接访问,也可以通过类的实例化对象访问,一般不推荐通过实例化对象访问,通俗的讲static变量属于类,不属于对象,任何实例化的对象访问的都是同一个static变量,任何地放都可以通过类名来访问static变量。
03.用static静态变量潜在性问题
- 用static静态变量潜在性问题
- 1.占用内存,并且内存一般不会释放;
- 2.在系统不够内存情况下会自动回收静态内存,这样就会引起访问全局静态错误。
- 3.在Android中不能将activity作为static静态对象,这样使activity的所有组件对象都存入全局内存中,并且不会被回收;
04.静态变量的生命周期
- 静态变量的生命周期
- 类在什么时候被加载?
- 当我们启动一个app的时候,系统会创建一个进程,此进程会加载一个Dalvik VM的实例,然后代码就运行在DVM之上,类的加载和卸载,垃圾回收等事情都由DVM负责。也就是说在进程启动的时候,类被加载,静态变量被分配内存。
05.静态变量何时销毁
- 静态变量何时销毁
- 类在什么时候被卸载?在进程结束的时候。
- 说明:一般情况下,所有的类都是默认的ClassLoader加载的,只要ClassLoader存在,类就不会被卸载,而默认的ClassLoader生命周期是与进程一致的
06.静态引用的对象回收
- 静态引用的对象回收
- 只要静态变量没有被销毁也没有置null,其对象一直被保持引用,也即引用计数不可能是0,因此不会被垃圾回收。因此,单例对象在运行时不会被回收
07.静态方法变量内存图
- 描述Dog对象:
public class Dog { public static String name; public static int age; public static void showNameAge() { System.out.println("name:" + name + " age:" + age); } }
- main测试方法:
public class Demo01 { public static void main(String[] args) { Dog.name = "阿白"; Dog.age = 98; Dog.name = "李双"; Dog.age = 90; Dog.showNameAge(); } } //执行结果:name:李双 age:90
- 以上案例对应内存图
- 大概流程就是
- 1.执行 java Demo01 是给JVM发送指令,和JVM说:把这个 Demo01.class 去执行;
- 2.JVM就去执行 Demo01.class 文件里面的字节码,首先第一步 是把 Demo01.class字节码加载进内存;
- 3.第二步把Demo01.class放入字节码存放区;
- 4.第三步把Demo01里面的静态数据(静态变量 与 静态方法)分配到 静态区;
- 5.第四步main方法进栈,如何进栈的,是把静态区里面的main方法拿到运行区(栈) 然后就进栈了;
- 6.第五步main方法执行 Demo. 的时候,就在此时 才把Dog.class加载进内存;
- 7.第六步把Dog.class放入字节码存放区;
- 8.第七步把Dog里面的静态数据(静态变量 与 静态方法)分配到 静态区;
- 9.第八步 在main方法中执行 Dog.name 是向静态区去找到 Dog.name 拿来使用,由于是共享的 name 只保持最后修改的数据;
其他介绍
01.关于博客汇总链接
02.关于我的博客
- 我的个人站点:www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:[email protected]
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e