java static 总结

来源:互联网 发布:京都小众景点.知乎 编辑:程序博客网 时间:2024/06/07 16:36

首先来介绍一下java中的存储空间类型:

在Thinking in java里,列举了Java的六种存储类型

1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制.

2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

3. 堆:存放所有new出来的对象。 
4. 静态域:存放静态成员(static定义的) 
5. 常量池:存放字符串常量和基本类型常量(public static final)。 6. 非RAM存储:硬盘等永久存储空间  
这里我们主要关心栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。 对于字符串:其对象的引用都是存储在栈中的,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中,如果是运行期(new出来的)才能确定的就存储在堆中。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。 如以下代码:

1.寄存器
编写过汇编程序的应该对寄存器非常熟悉,那时候用的ax,bx,cx,dx等等。寄存器在CPU里面,所以速度特别快,但是数量非常有限。在java中无法直接和寄存器打交道,不过在c中是可以声明寄存器变量的。

2.栈空间
写过汇编的肯定感到非常亲切,在汇编程序里不就是压栈和出栈吗?有一个指针控制栈空间,分配空间是栈指针上移,就是push操作,释放空间指针下移,就是pop操作。当然C和C++也主要是通过栈分配空间的。因为只要压栈和出栈,所以速度特别快。java中的对象引用是通过栈分配的,而java对象不是通过栈分配的,这也是java效率相对差一些的原因吧。通过栈分配空间有一个限制就是必须在编译时确定空间大小,也就是程序运行前就应该可以知道运行时内存的情况。比如mov ax,4这条指令占用多少个字节在编译时是确定的。

3.堆空间
就是一个大的内存块,需要的时候就申请分配,java中的对象都是在堆中非配的。但是堆空间的回收是比较麻烦的,所以JVM的回收算法都比较复杂。但是如果堆空间比较大,也就是内存没有面临用完的话,JVM一般不会启动垃圾回收器。这种情况下堆的效率和栈应该差不多,只是堆没有回收空间而已。如果要不时的启动GC的话,可以想象效率会极其低下。

4.静态存储区
声明为static的变量因为他们一直存在(整个程序运行过程中),所以他们被保存在一个静态存储区。

5.常量储存区
声明为final static的为常量,可以保存在常量储存区,还有String类型的对象都是常量,系统维护了一个String常量池。

6.其他存储
非RAM存储器,主要就是磁带,磁盘等等。

这里最关键的应该是栈和堆,栈应该是应用最广泛的,在汇编中函数调用的时候一般是这样的过程:
1.压栈(保护现场)
2.进入方法调用
3.出栈(恢复现场)
这里只是简单的描述,上面的过程可能会有好多嵌套,不过大致过程就是这样,在其他语言其实也是一样的。 

只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们。因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象。


一般来说,执行new来创建对象存储空间才被分配,其方法才被外界调用,有两种情形是无法解决的,

一种是只想为某特定领域分配单一存储空间,不需要考虑创建多少对象,甚至不创建对象。

一种是即使没有创建对象也可以调用这个方法。

static 关键字可以满足这两方面的需要。当声明一个是static ,就意味着这个域或方法不会与包含它的那个类的任何对象实例关联在一起。

类数据,类方法 代表整个类而不是类的某个对象而存在。


1 static变量

 

class  staticTest{          static int i = 47}StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
调用有两种方式

1 st1.i ++;

2 staticTest.i++;



2 static 方法




0 0
原创粉丝点击