String,你到底创建了几个对象????
- String str=new String("aaa");
 
这行代码究竟创建了几个String对象呢?答案是2个,而不是3个。由于 new String("aaa")相当于"aaa"与一个就是创建出来的放在堆时原实例对象,而另一个就是放在常量池中的 "aaa" 对象,当然这里的str本身只是一个引用,放在栈里,用来指向堆中创建出来的对象。
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
- String str="aaa";
 
只创建1个对象。这里涉及到字符串常量池,在JVM中有一个字符串池,它用来保
存很多可以被共享的String对象,这样如果我们在使用同样字面字符串时,它就使用字符串池中同字面的字符串。当然我们可以使用String对象的
intern()方法来访问String对象在字符串池中所对应的常量对象。
上面这行代码被执行的时候,JVM先到字符串池中查找,看是否已经存在值为"aaa"的对象,如果存在,则不再创建新的对象,直接返回已存在对象的引用;如果不存在,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。
- String str1="aaa";
 - String str2="aaa";
 
也只创建1个对象。能过上面的解释这个就更清楚了,在执行第二行代码时,aaa字符串对象在池中已存在,所以直接返回池中已存在的那个字符串对象。
- String str="aaa"+"bbb";
 
还是只创建1个对象。由于常量字符串是在编译的时候就也被确定的,又
因"aaa"和"bbb"都是常量,因此变量str的值在编译时就可以确定。这行代码编译后的与String
str="aaabbb";是一样的,这与我们平时好像不太一样啊?一般使用“+”连接两个字符串都会产生另一个新的字符对象。下面我们看一下例子就明白
了:
- String str1 = "aaa";
 - String str2 = "bbb";
 - String str3 = "aaabbb";
 - String str4 = "aaa" + "bbb";//不会产生新的字符串对象
 - System.out.println(str3 == str4);//true
 - str4 = str1 + "bbb";//会产生新的字符串对象
 - System.out.println(str3 == str4);//false
 - str4 = str1 + str2;//会产生新的字符串对象
 - System.out.println(str3 == str4);//false
 
从上面例子我们就可以得出:使用“+”连接的两个字符串本身就是字面常量字符串时,如果池中存在这样连接后的字符串,则是不会重新创建对象,而是直接引用池中的字符串对象;如果“+”连接的两字符串中只要有一个不是字面常量串(即定义过的),是会产生新的字符串对象。
凡事也有例外,这个也不例外:如果“+”连接的字符串中两个或一个不是“字面常量”,但如果定义成常量字符串时,情况又有变化:
- final String str1 = "aaa";
 - final String str2 = "bbb";
 - String str3 = "aaabbb";
 - /*
 - * 因为str1与str2都定义成了常量,所以编译时就能确定,编译时就会将常量替换,等同于
 - * str4 = "aaa"+"bbb",因此不产生新对象
 - */
 - String str4 = str1 + str2;
 - System.out.println(str3 == str4);//true
 
但如果先定义final字符串,但未在定义处初始化,而初始化在块中,如下:
- //此时str1与str2相当于变量,而不是常,因为块是在运行时才能确定,在编译时不能确定
 - final static String str1;
 - final static String str2;
 - static {
 - str1 ="aaa";
 - str2 ="bbb";
 - }
 - public static void main(String[] args){
 - String str3 = str1 + str2;
 - String str4 ="aaabbb";
 - System.out.println(str3==str4); //输出为false
 - }
 - String str=" ";与String str=new String();
 - str=" "会放入池中,但new String()不会放入池中。
 
String的intern()方法 
“当
调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object)
方法确定),则返回池中的字符串;否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。它遵循对于任何两个字符串 s 和
 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为
true”,这是jdk文档原文注解。
现在我们回到最开头的那个例子,为什么String str=new
String("aaa");会产生2个对象?一个是"aaa"又作为字符串构造函数的参数,但"aaa"自己就是一个字符串,在传进构造函数前就已创建
了一个字符对象,实质上与就好比是第二个实例:String str="aaa";
,它创建的字符串对象会放入到池中,并且引用的也是池中的那个字符串对象;另一个就是通过new String()构造函数创建的。所以new
String("aaa")会产生两个对象,也就是说通过此种方式创建字符串对象时,会先将字符串参数对象放入对象池,然后另外创建一个字符串对象。
理
解完new String("aaa")为什么会产生两个对象,我们再来看看new String(char
value[])这样的方式创建时,又会不会把字符串对象放入到池中呢?答案是不会的。因为传递给构造函数的是一个字符数组,而不是像前面传递的是一个字
面常量字符串参数那样,将字符串参数本身放入池中。那么我们现在如果证明new String(char
value[])未将字符串对象放入池中,我们可以写一个简单的测试,运行时打开XP的任务管理器,查看操作系统的内存使用情况就可以初步确认:
- int size = 10000000;
 - char c[] = new char[size];
 - for (int i = 0; i < size; i++) {
 - c[i] = 'a';
 - }
 - //使用带字符数组参数构造函数创建字符串时,字符串对象不会放入字符串池
 - String str1 = new String(c);
 - System.out.println("String字符串对象创建完毕...");
 - Thread.sleep(5000);
 - str1.intern();//到里会看见内存增加
 - System.out.println("第一次调用intern()完毕...");
 - Thread.sleep(5000);
 - str1.intern();//再过5秒将看不到内存增长,因为池中有了,不会再放入,所以内存无变化
 - System.out.println("第二次调用intern()完毕...");
 - Thread.sleep(5000);
 
所以创建字符串对象放入并放入池中有二种方式:第一种就是直接使用字面常量定义
字符串时,如 String str="aaa";
,str会引用放入池中的对象;第二种就是使用带字符串参数的字符串构造函数,并且此时传入的参数值要是字符串常量形式,而不能是变量的形式,也就是说只
能是 String str=new String("aaa");形式,而不能是先定义 String s = "aaa",然后再使用 String
 str=new String(s);来创建对象,new
String(s);此时只创建一个对象,但如果池中不存在时我们可以使用intern方法将它放入池中。当然上面放入池中的前提是池中还不存在这些字符
串对象。
其实,当我们仔细研究时,发现放入池中只实质上只存在一种时机,那就是:直接使用字面常量字符串时。上面所说的两种时机实质上就是直接使用了字面常的字符串而将其放入池中的。
上面多处提到了JVM中的堆栈,下面小结一下各自原作用:
栈用来保存基本类型与对象的引用的,基本型在创建前会查看Stack中是否已经有, 有则指向, 没有则创建。
String内部是以字符串数组来存储字符串的,因此可以认为与char[]等同, String a= "abc",首先在Heap中创一个对象,再到Stack中找char[]是否存在,有则指向该地址, 无则在Stack中创建数组。
new出来的都是在Heap中,堆是用于存储对象的。
String,你到底创建了几个对象????的更多相关文章
- new String("ab")到底创建了几个对象说明
		
new String("ab")到底创建了几个对象? 之前一直被这个问题困扰,网上一些描述的都不是很清楚,自己看了一些资料可算搞清楚了,那就在博客上记录一下吧! String st ...
 - String,到底创建了多少个对象?
		
String str=new String("aaa"); <span style="font-size:14px;">String str=n ...
 - Java String Pool--String s = new String("a") 到底创建了几个对象?
		
本篇重点(tips): 1. String Pool 是以Java 中 String 对象是不可变的这一特性为基础的 2. String Pool是Heap(堆)中的一块特殊空间(JDK 1.7 之前 ...
 - String s="a"+"b"+"c",到底创建了几个对象?
		
首先看一下这道常见的面试题,下面代码中,会创建几个字符串对象? String s="a"+"b"+"c"; 如果你比较一下Java源代码和反 ...
 - new String创建了几个对象
		
String str = new String(“abc”) 到底创建了几个对象? 首先String str是定义了一个字符串变量,并未产生对象,=不产生对象,那么只有后面的new String(& ...
 - 工作10年后,再看String s = new String("xyz") 创建了几个对象?
		
这个问题相信每个学习java的同学都不陌生,作为一个经典的面试题,到现在工作这么多年了我真是认为挺操蛋的一个问题,在网上到现在你仍然可以看见很多讨论这个问题的人,其中不乏工作很多年的人都有争论,我认为 ...
 - String s = new String("aa") 创建了几个对象?
		
1 最近几个同学面试的时候出现了这样一个问题 刚听到这个题目的时候的确是不知所措: 经过网上的查找和自己的理解来解释一下这个题目的答案 答案是: 为什么呢??? 1 实现我们都知道创建实例有两种方法 ...
 - new String("123") 创建了几个对象?
		
String 对象可谓再熟悉不过了,与此相关的面试题经常会引出内存性能优化的问题,本篇主要以 new String("123") 创建了几个对象为例记录. 一.你能回答正确吗 St ...
 - Item 5 避免创建不必要的对象
		
场景一: 这个是经常出现的问题,因为我们经常误用String. public class Test { public static void main(String[] args) { //参数&qu ...
 
随机推荐
- BZOJ1050 [HAOI2006]旅行
			
其实这道题根本不用最短路算法... 我们可以就把边从小到大排序,那么只需要枚举大小两个端点,把中间的边都加进去判断联通性即可. 判断联通性显然用的是并查集. #include <cstdio&g ...
 - Android mtk单路录音问题
			
在单路录音中,有两种情况导致底层录音资源被占用的问题: 1 开启vmLog后,拨打一个电话,挂断电话.如果挂断电话后,没有关闭vmlog进程,则会导致其它AP 无法得到底层的录音资源,从而无法录音. ...
 - 大神的游戏(codevs 1353)
			
题目描述 Description 在那遥远的机房,有一片神奇的格子.为了方便起见,我们编号为1~n.传说只要放入一些卡片,就能实现愿望.卡片一共有m种颜色,但是相邻的格子间不能放入相同颜色的卡片.只要 ...
 - hadoop机架感知
			
背景 分布式的集群通常包含非常多的机器,由于受到机架槽位和交换机网口的限制,通常大型的分布式集群都会跨好几个机架,由多个机架上的机器共同组成一个分布式集群.机架内的机器之间的网络速度通常都会高于跨机架 ...
 - C#的面向对象特性之封装
			
在C#语言中,共有五种访问修饰符:public.private.protected.internal.protected internal. public 公有访问.不受任何限制.private 私有 ...
 - Ubuntu安装dos2unix工具
			
Ubuntu下默认没有安装dos2unix工具,而且也没有一个叫这个名字的工具(我在solaris里用过dos2unix,不知道为啥Ubuntu没有).但是有一个替代工具——tofrodos , 下面 ...
 - asp.net获取客户端IP方法(转载)
			
最近web获取客户端ip,看到下面这篇文章,转载过来,一起分享(转载地址:http://www.cnblogs.com/yejun/archive/2008/02/26/1082485.html) 通 ...
 - 如何将win7安装到 移动硬盘/U盘 及 VHD、BCD等相关知识 链接汇总
			
如何将win7安装到 移动硬盘/U盘? 从u盘启动win7/2008 R2的方法,更新:换机器免sysprep的方法:http://www.360doc.com/content/11/1103/14/ ...
 - IE下AjaxForm上传文件直接提示下载的兼容性Bug
			
使用AjaxForm上传文件时候,在IE下直接提示下载保存: 我的示例代码: return this.Json( new { prop1 = 5, prop2 = 10 }); 这种问题只出现在IE下 ...
 - hdu 1756 判断点在多边形内 *
			
模板题 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> ...