Java内存分配原理精讲
?
就等价于String s = "abc";??
String? a? =? "a";??
String? b? =? "b";??
String? c? =? "c";??
String? s? =?? a? +? b? +? c;?这个就不一样了,最终结果等于:
- StringBuffer?temp?=?new?StringBuffer();??? ?temp.append(a).append(b).append(c);??? ?
- String?s?=?temp.toString();?
由上面的分析结果,可就不难推断出String 采用连接运算符(+)效率低下原因分析,形如这样的代码:
- public?class?Test?{ ?public?static?void?main(String?args[])?{ ?
- String?s?=?null; ?for(int?i?=?0;?i?<?100;?i++)?{ ?
- s?+=?"a"; ?} ?
- } ?}?
每做一次 + 就产生个StringBuilder对象,然后append后就扔掉。下次循环再到达时重新产生个StringBuilder对象,然后 append 字符串,如此循环直至结束。如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和销毁对象的时间。所以对于在循环中要进行字符串连接的应用,一般都是用StringBuffer或StringBulider对象来进行 append操作。
String对象的intern方法理解和分析:
- public?class?Test4?{ ?private?static?String?a?=?"ab";? ?
- public?static?void?main(String[]?args){ ?String?s1?=?"a"; ?
- String?s2?=?"b"; ?String?s?=?s1?+?s2; ?
- System.out.println(s?==?a);//false ?System.out.println(s.intern()?==?a);//true?? ?
- } ?}?
这里用到Java里面是一个常量池的问题。对于s1+s2操作,其实是在堆里面重新创建了一个新的对象,s保存的是这个新对象在堆空间的的内容,所 以s与a的值是不相等的。而当调用s.intern()方法,却可以返回s在常量池中的地址值,因为a的值存储在常量池中,故s.intern和a的值相等。
总结
栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容
堆中存放使用new关键字创建的对象.
字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。