关于java内存

来源:互联网 发布:大图分割打印软件 编辑:程序博客网 时间:2024/06/08 16:25

Java与内存

Java的内存分为4大块:heapsegment,stack segment,code segment,data segment

分别是:堆,栈,代码区,静态区。

堆:所有通过new出来的对象都放在堆中。

栈:基本数据类型,引用

代码区:程序的方法都放在这儿

静态区:静态变量都放在这儿

另外,在.class文件中,会对文件中的常量存放在常量池和静态常量池中(这两个池都在.class中)。也就是说,在程序中出现“abc”这个常量,在编译成.class文件时,就已经存放在常量池中了。

问:String s=new String("abc");中创建了几个对象?

答:两个,一个匿名对象,内容为abc。另一个通过new形式创建。

原因:API String中有如下语句:Java 程序中的所有字符串字面值(如 "abc")都作为此类的实例实现。

再次:根据Stringtemp="abc";

                      String s=newString(temp);

你可以更清楚的看出到底产生了几个对象。

问:String s="a"+"b"+"c";中创建了几个对象?

答:产生了四个对象,三个匿名的String对象,一个匿名的StringBuilder对象。

依据:String的API:Java语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或StringBuffer)类及其 append 方法实现的。

解释:上面这条语句等价于:

String s=newSringBuilder("a").append("b").append("c").toString();其中"a","b","c"都是匿名的对象,至于为什么,请查看今天的第一个知识点(Java与内存)。

问:如下程序中,输出结果分别是什么?

public classTest1{

publicstatic void main(String[] args){

Test1 t=new Test1();

Aa=new A();

a.m=1;

t.f2(a);

System.out.println(a.m);

t.f1(a);

System.out.println(a.m);

}

publicvoid f1(A a){

a.m=2;

}

publicvoid f2(A a){

a=newA();

a.m=3;

}

}

class A{

intm;

}

控制台结果:

1

2

原因:需要注意的是,new 创建的对象在堆中,而引用是在栈中,一个引用等于另一个引用时,两个引用指向同一个堆中的对象。

上面A a=new A(); a.m=1;在堆中产生了一个A的对象,其中m的值为1;

调用f2方法,注意f2这两个字母的后面括号中的内容(A a),这意味着又创建了一个名为a的引用,但和main中的a不同,两个都叫a,但存放在栈中的位置是不同的,然后,将main中的a传入方法f2,即令f2中的a等于main中的a,两个不同的引用指向同一个堆中的对象。那么可以想象到,当在f2中改变a的引用后,方法运行完,f2中的a销毁,main中的a是不会改变的,因为它们本身就是不同的。

但是,像f1那样,虽然a不同,但是a.m,即两个引用指向的堆中的对象是同一个,改变的是同一个对象中属性的值,即使f1中的a销毁,值仍然改变了。

结论:对于调用方法但是没有返回值的情况,注意是引用改变,还是引用所指向的对象中的属性改变。

小技巧:一般调用方法时,看引用后面是等号,说明引用改变了,引用后面是点,说明对象内容改变了。

原创粉丝点击