博客园 首页 私信博主 显示目录 隐藏目录 管理 动画 动画

理解 static (深入了解JAVA虚拟机)

谈谈我对static的理解

 

因为我发现很多同学学到这里都会很困惑 很难理解static到底是个什么 

首先 static是个修饰符 被static修饰的变量我们统称为静态变量也叫类变量(为什么叫类变量呢 ?因为我们可以直接使用类来调用被static修饰的变量)

static 不可以修饰局部变量!牢记 

再和大家说一下另一种变量 也同样是成员变量 但是没有被static修饰 我们叫它全局变量也是很多人嘴里的动态变量(c中的叫法) 我有个比较更容易的记法 我叫它实例变量 即非静态变量

(对象是类实例化来的大家肯定不陌生 而非static变量想要调用的时候需要用对象(点) 所以我称之为实例变量)

对于静态变量在内存中只有一个拷贝!JVM只会在加载类时为静态分配一次内存 静态变量是可以通过对象来访问的

对于非静态变量!你每new一个实例 JVM中就会为你分配一次内存 实例变量可以在内存中有多个拷贝 不影响彼此(灵活性)

static变量在RAM ROM中的存储 存储在数据存储区和堆 栈 不是一个存储区

插一嘴 讲下堆和栈 

下面的听不懂的同学可以先不看!

 

stack 空间小 速度比较快  用来放对象的引用
heap 大 一般所有创建的对象都放在这里 

栈(stack):是一个先进后出的数据结构 通常用于保存方法(c:函数)中的参数 局部变量八种基本类型和自定义对象的引用(c:指针)被执行的方法也会到栈中 执行完会出栈

在java中 所有基本类型和引用类型都在栈中存储 栈中数据的生存空间一般在当前scopes内(就是由{...}括起来的区域) 

堆(heap):是一个可动态申请的内存空间(其记录空闲内存空间的链表由操作系统维护),C中的malloc语句所产生的内存空间就在堆中.

在java中,所有使用new xxx()构造出来的对象都在堆中存储,当垃圾回收器检测到某对象未被引用,则自动销毁该对象.所以,理论上说

java中对象的生存空间是没有限制的,只要有引用类型指向它,则它就可以在任意地方被使用.

1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。


2. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享。

堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。

3. Java中的数据类型有两种。

一种是基本类型(primitive types), 共有8种,即int, short, long, byte, float, double, boolean, char(注意,并没有string的基本类型)。

这种类型的定义是通过诸如int a = 3; long b = 255L;的形式来定义的,称为自动变量。值得注意的是,自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。

如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),

出于追求速度的原因,就存在于栈中。

另外,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

int a = 3;
int b = 3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;

在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。


这样,就出现了a与b同时均指向3的情况。特别注意的是,这种字面值的引用与类对象的引用不同。


假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。


相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。 如上例,我们定义完a与b的值后,再令a=4;

那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。

因此a值的改变不会影响到b的值。

另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是

要占用更多的时间。

4.String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建(作为对比,

现在回到我们讲的static

 static修饰的变量讲完了 下面讲下static修饰的方法  

静态方法有什么好处呢 静态方法不需要类实例化对象 就可以直接调用

在堆和栈里面我们说过 对象是个占用内存相对比较多的东西

也就是说被static修饰过的方法 不再归对象所有 而是属于类 当然对象.还是可以调用 这在我看来是不合理的!不推荐使用 推荐直接使用类名调用 如果你看见了一个通过类名直接调用的方法或变量 那么他一定是static的

和大家说下static的弊端 static会从你JVM加载类开始 就一直存在 直到整个程序结束才会释放!所以请慎用 ! 

static我个人喜欢把他作为工具来使用 因为不需要new对象就可以直接用了 例如我们以后要连接数据库 就可以使用static修饰的方法 因为连接数据库并不是某一个对象所特有的 他只是一个工具

最后给大家讲个static修饰的代码块

静态代码块和静态方法的区别在于

静态代码块是自动执行的 而方法是你调用他的时候才会执行

静态方法只能直接调用本类中其他的静态成员(变量 方法) 静态无法调用非静态(先上车后上车)在JVM中被static修饰的会被首先被载入 而这个时候其他未被static修饰的还没有载入 所以是调用不到的

行了 累了= =不写了 自己多理解 不会的抽时间问我吧

下面给你们附上一幅JVM3个我讲到的存储区=。=自己理解  

 

 

 

 

 

 

  

 

posted @ 2018-06-09 17:46  这才是真的阿呆云飞  阅读(3192)  评论(0编辑  收藏  举报