java中局部变量、实例变量和静态变量在方法区、栈内存、堆内存中的分配

1、java中的变量与数据类型

变量是一个容器,用来装什么的呢?装内存地址,这个内存地址对应的是内存中某个数据。
那为什么这个容器不直接装这个数据更简洁呢?因为直接装数据的话,这个数据就无法被别的变量使用,无法复用就会导致很多不便。
所以变量的内存分配可以看成两个不部分:1、变量在内存中的分配(“变量分配”) 2、变量所引用的数据在内存中的分配(“数据分配”)

1.1、变量类型有:

局部:在方法内声明的变量
实例:在类中但在方法外声明并且没有static
静态:声明为static的变量

1.2、变量的数据类型有:

1、原始数据类型 2、引用数据类型

2、思考

原始数据类型变量的“变量分配”和“数据分配”是在一起的(都在方法区或栈内存或堆内存,这里思考什么时候在方法区、什么时候在栈内存、什么时候在堆内存???)
引用数据类型的“变量分配”和“数据分配”不一定是在一起的(什么情况是在一起的?什么情况不在一起?)

3、例子:

public class Fruit {

 private static int x = 10;
 static BigWaterMelon bigWaterMelon_1 = new BigWaterMelon(x);

 private int y = 20;
 private BigWaterMelon bigWaterMelon_2 = new BigWaterMelon(y);

public static void main(String[] args) {
    Fruit fruit = new Fruit();
    int z = 30;
    BigWaterMelon bigWaterMelon_3 = new BigWaterMelon(z);


    new Thread() {
        @Override
        public void run() {
            int k = 100;
            setWeight(k);
        }

        void setWeight(int waterMelonWeight) {
            fruit.bigWaterMelon_2.weight = waterMelonWeight;
            System.out.printf(fruit.bigWaterMelon_2.weight + "");
        }

    }.start();
}
}

class BigWaterMelon {

 int weight;

 BigWaterMelon(int weight) {
    this.weight = weight;
 }
}
image.png

3.1、分析:

栈:

1、栈内存中按线程粒度来划分区域。

比如划分为:主线程、new Thread线程、其他线程等等

2、每个线程区域中又按方法粒度来划分区域。

比如:主线程区域中划分了一块区域:main();new Thread线程中划分了两块区域:setWeight()、run()

3、每块方法区域中包含其所有的局部变量。

比如main()方法这块区域中包含局部变量:String[] args、Fruit fruit、int z = 30、BigWaterMelon bigWaterMelon_3
这里可以看到String[] args、Fruit fruit、BigWaterMelon bigWaterMelon_3这三个局部变量在这里只存储了变量,而没有存放变量的数据,而int z = 30既存放了变量int z 也存放了变量的数据30。这就可以肯定上面的第一条结论“栈内存中,基本数据类型的变量和变量的数据是存放在一起的”,这里要注意:只是说存放在一起,但没说是一起在栈内存,也可能一起在堆内存或者方法区,继续往下分析。

方法区:

1、方法区中按class粒度来划分区域。(所以方法区存储的都是只加载一次的)

比如:Fruit.class、BigWaterMelon.class、Fruit$1.class(这是个什么玩意?后面解释)

2、在每块class区域中包含其所有的静态变量。(所以方法区存储的都是只加载一次的)

比如:Fruit.class中包含static int x = 10、static BigWaterMelon bigWaterMelon_1。这里又出现了基本数据类型,和在栈内存中一样,基本数据类型的变量和变量的数据存放在一起,和栈内存中唯一不同的是,栈内存中是局部变量,而方法区中是静态变量。

堆:

1、堆内存中按实例和其所包含的非静态变量划分区域。

比如:
1、new String[] 对应的变量是栈内存中的 : String[] args;
2、new BigWaterMelon()+int weight = 10 对应的变量是方法区中 :static BigWaterMelon bigWaterMelon_1;
3、new BigWaterMelon()+int weight = 30 对应的变量是栈内存中 :BigWaterMelon bigWaterMelon_3;
4、new Fruit()+int y = 20+BigWaterMelon bigWaterMelon_2 对应的变量是 栈内存中 :Fruit fruit;
5、new BigWaterMelon()+int weight = 20 对应的变量是同在堆内存中的 : BigWaterMelon bigWaterMelon_2;
6、new Fruit$1() 没有对应变量,因为它是匿名的,在方法区中存在它的类文件Fruit$1.class(这是个啥东西往下看)

前面一直搞不明白Fruit$1.class这是个什么玩意,找编译后的文件看一下:

image.png

其实就是一个Thread类。。。只是因为我们用了匿名对象,所以给我们生成了一个这么个玩意,那如果我们把new Thread放在别的类中试试会怎么样,新建一个Test.class如图:
image.png

为了简介,我把Thread对象中所有东西都注释了。在编译后得到:
image.png

打开看看:
image.png

果然就是一个Thread类,所以匿名对象其实会生成一个class文件,类名就是由匿名对象存在的类名字后面加$和数字拼成。原谅我的基础辣鸡。。。
好了,重新描述一下上面堆内存的第六条就可以这么说:
6、new Fruit$1()(即new Thread()) 没有对应变量,因为它是匿名的,在方法区中存在它的类文件Fruit$1.class。
这下就好理解了。
我们在回头看Fruit$1.class文件,可以看到他有一个构造函数:
image.png

Fruit$1(Fruit paramFruit) {}
所以在堆内存中的形式应该是new Fruit$1()(即new Thread())+Fruit paramFruit,其中Fruit paramFruit变量对应的实例就是堆中的第4条。

3.2、结论

3.2.1、“变量的分配”:

局部变量在栈内存,静态变量在方法区,实例变量在堆内存。 也就是三个内存中都有变量。

3.2.2、“数据的分配”:

原始数据类型跟随自己的“变量分配”在一起,相亲相爱。
引用数据类型在堆内存中。

完毕。
有不对的地方请指导。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • 第二部分 自动内存管理机制 第二章 java内存异常与内存溢出异常 运行数据区域 程序计数器:当前线程所执行的字节...
    小明oh阅读 1,089评论 0 2
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,036评论 1 32
  • 一 运行时数据区域 jdk1.7中, Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的...
    凯玲之恋阅读 1,658评论 0 5
  • 整理来自互联网 1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具...
    Ncompass阅读 1,516评论 0 6
  • 影响你生活的14个心理效应: 1、野马效应 吸血蝙蝠吸取野马的血为食,但所吸的血量极少,远不足以使野马死去,...
    阿甘1972阅读 90评论 0 0