【Java EE】Java代码的内存分析

【前言】

      软件设计师考试准备那会第一次看J2SE的视频,算是Java学习的敲门砖,了解到了Java是一门面向对象的语言,提供程序运行的解释环境,是比较健壮的语言。现在时隔近两个月,再次复习J2SE的视频,对于知识的理解更清晰,动手实践印象更加深刻。本篇博客介绍面向对象章节中的内存分析,希望可以给读者带来收获。

 

【举栗说明】

      面向对象中内存的介绍,是非常基础的一块内容,明白代码在内存中如何变幻分配,对于代码的书写和理解都会有所进步。下面看看栗子,带你理清代码和内存分布之间的关系。

 

栗子1

public class Person{
	int id;
	int age=20;

	Person(int _id, int _age){
			id = _id;
			age= _age;
        }
		
	public static void main(String[] args)	{
			Person tom =new Person(1, 25);
	}

}

      上面的代码是一个Person类,大概分三块来看,第一块——两个成员变量id age,第二块——一个Person方法,第三块——还有一个main方法。

      开始执行main方法,首先,我们发现Person new出来了一个新的Person对象,在内存中体现就是先在栈开出了一块内存存放 tom以及它的地址,堆中也开出了一个内存存放新new出来的对象。通过栈中tom的地址,我们就可以找到位于堆中的新对象。

       new Person1,25)使用到了Person方法,注意看代码第二块内容,你会发现Person方法里正好有两个参数,_id _age ,对应着 1 25,别看它们是两个小不点,作为局部变量也是要在栈中占用两块地方的, _id的值为1 _age的值为25,赋值给idage之后,堆中的idage值发生改变。Person方法就调用结束,结束之时也是局部变量在栈中消失的时候,虽然它们轻轻的走了,但是它们的数据保留在了堆中。

       跟着上面的思路,你是不是开始在脑海中,劈开一块空间来做内存的分布了呢?快来看看下面的内存分布图。(PS:虚线表明方法调用后会消失的哦)

     

                    

栗子2

      上面的栗子算是一道开胃小菜,下面再来看段代码。

Public class Test{
    Public static void main(String args[]){
        Test test=new Test();
        int date=9;
        BirthDate d1=new BirthDate(7,7,1970);
        BirthDate d2=new BirthDate(1,1,2000);
        test.change1(date);
        test.change2(d1);
        test.change3(d2);
            … …
}

     Public void change1(int i) {
          i=1234;
         }
     Public void change2(BirthDate b){
            b=new BirthDate(22,2,2004);
         }   
     Public void change3(BirthDate b){
            b.setDay(22);
        }
}

       PSBirthDate方法,b.setDay代码不是本块主要部分,没有贴相关代码。

      上面的代码乍一看一大片,其实仔细看来也就大概两部分,按照第一个栗子的思路,new Test出现,看到new一个对象,就要想到栈和堆的开辟,这个思路不错。接着,int date=9,诶,这个直接给int类型的date变量赋值了,这怎么在内存中体现呢?

      在这里就有一个大福给读者了,小tips哦,Java中的四类八种属于基本的数据类型,这四类八种在内存中只占有栈内的一块内存就OK。除了这四类八种,我们都叫做“引用类型”,引用类型会占用两块内存,栈一块,堆一块。看下图↓

 

                              

 

      小知识点说完,我们接着看内存的分布,date在栈中有一块空间放着数据9,这一关过了。下面两句又是两个new新对象的代码,再往下走,看到test.change1date),看起来是调用了Test类中的方法了,找到这个方法,发现change1方法有参数i,正好和date对应嘛,方法中把1234赋值给了i .所以之前存放date数据9的栈中内存块有了一个变量名i做标记,调用过change1方法后,数据9就变为了1234。因为i为局部变量,方法调用过后,它就在栈里消失了。

      再往下走,两个局部变量d1,d2出现,千万别忘记给他们俩在栈上开出两块空间存放它们各自的地址,change2方法和前面的new情况类似,只不过在它调用结束后,栈上的局部变量立即消失,堆里new出来的那个对象失去了引用指向,不久后就会有神奇的Java垃圾收集器带走它。

      我们来看看change3方法,change3调用了BirthDate对象内部的方法,改变了Day的数据为22    

      经过上面的思路带动,你的脑袋有没有跟着思考,笔有没有跟着尝试画一画呢?看下图,来看看我们俩个画的一不一样。

                            

  

       PS通过上面的内存分析,不知道你有没有发现一个小秘密,局部变量的确会在栈内存有一席之地,不过,执行完它对应的方法它就消失掉了,因他而生的堆中的对象也会在不久后被垃圾收集器带走。但是,像change3这样调用对象内部方法,对堆的改变是永久性的,直到这个main方法执行结束。

 

【小结】

      之前王聚师傅同我们交流大话设计模式的时候,就在小白板上一遍遍画内存的分布变化,一句句代码对应的相当清晰,当时就觉得,师傅真厉害。等到如今,自己又一次回顾这块知识,自己笔下画来画去的时候,又是别样的一番收获。尤其是在写这篇博客的过程中,又是一次学习和锤炼。

      温馨提示:内存分布知识很基础,扎好这Java的马步很重要哦~希望本篇博客能给读者带来一些收获,下次见~~


评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值