new String()究竟创建几个对象?
来源:互联网 发布:网络基本结构 编辑:程序博客网 时间:2024/04/28 05:39
new String()究竟创建几个对象?
1. 由来
遇到一个Java面试题,是关于String
的,自己对String
还有点研究?下面是题目的描述:
在Java中,
new String("hello")
这样的创建方式,到底创建了几个String
对象?
题目下答案,各说纷纭,有说1个的,有说2个的。我觉得都对,但也都不对,因为要加上一定的条件,下面来分析下!
2. 解答
2.1. 分析
题目中的String
创建方式,是调用String
的有参构造函数,而这个有参构造函数的源码则是这样的public String(String original)
,这就是说,我们可以把代码转换为下面这种:
String temp = "hello"; // 在常量池中String str = new String(temp); // 在堆上
这段代码就创建了2个String
对象,temp
指向在常量池中的,str
指向堆上的,而str
内部的char value[]
则指向常量池中的char value[]
,所以这里的答案是2个对象。(这里不再详述内部过程,之前的文章有写,参考深入浅出Java String)
那之前我为什么说答案是1个的也对呢,假如就只有这一句String str = new String("hello")
代码,并且此时的常量池的没有"hello"
这个String,那么答案是两个;如果此时常量池中,已经存在了"hello"
,那么此时就只创建堆上str
,而不会创建常量池中temp
,(注意这里都是引用),所以此时答案就是1个。
当然,光说不练假把式,下面就来用例子验证一下:
2.2. 验证
不啰嗦,直接看第一段代码:
// 代码1public static void main(String[] args) { String str = new String("hello"); String after_str = "hello"; System.out.println(str + after_str);}
我们在println
语句那里加个断点,debug
下,如下图:
可以看到在代码1中,str
和after_str
不是同一个对象,这个应该没有疑问把,一个在堆上,一个常量池中,但是我们注意到str.value
和after_str.value
的地址确是同一个,即是同一个char
数组,所以可以理解为,当执行str
那句代码时,创建了两个String
对象,一个在常量池,一个在堆上,接下来到执行after_str
这句时,这种方式创建的字符串都在常量池中,但是如果常量中如果有,就直接返回了,所以这里返回的是上一句在常量池那里创建的String
,所以str
这句代码创建的是2个对象。
接下来再看一段代码:
// 代码2public static void main(String[] args) { String before_str = "hello"; String str = new String("hello"); System.out.println(str + before_str);}
同样在println
打断点,如下图:
在代码2中,str.value
和before_str.value
也是用的同一个char
数组,但这里的代码可不是和代码1相同的,这里我们把"hello"
提到前面创建,这也就是说明当执行str
那句代码时,没有再在常量池中创建"hello"
了,所以str
这句则是创建了1个对象。
2.3. 补充
这里突然想到,还要补充一下上面如果常量池中没有,则创建2个对象
,很多人会误解这句话的含义,这个常量池,不是你没手动的创建,常量池中就没有东西,这个理解是错误的,大家一定要修正它。在你的程序启动时,就已经装载来很多class
,这里面也有字符常量的创建,只是不是你自己创建的,你只是不知道而已。
例如下面这段代码:
// 代码3,JDK >= 1.7public static void main(String[] args) { String str1 = new StringBuilder("hel").append("lo").toString(); String str2 = new StringBuilder("ja").append("va").toString(); System.out.println(str1.intern() == str1); // true System.out.println(str2.intern() == str2); // false}
(关于intern
在不同JDK的不同表现,之前也说过了,详情请看深入浅出Java String)
代码3这里,str1
的结果是很多人都能理解的,但是str2
的结果为false
就说明,常量池中已经有了"java"
了,这里很多人不解,这个就是系统装入的字符常量,除了"java"
,类似的还有"false"
,"true"
(在java.lang.String
里)等等。但是这个"java"
我始终没找到在那个类中,可能在native
方法中把,知道的请告知下,谢谢!
3. 总结
通过这个面试题,可以看到String
真的是有很多”坑”,但是弄明白这些”坑”也是很有趣的。还有,这些都是我自己找资料,实践,总结,分析出来的,难免有错误存在,有发现的错误的同学,还请指正!
- new String()究竟创建几个对象?
- String str = new String("abc"), 这行代码究竟创建了几个 String 对象?
- String str=new String("123"); 究竟创建了几个对象
- Java中String s = new String("123")究竟创建了几个对象
- Strnig str = new String("123");究竟创建了几个String对象?
- Stringstr=new String("abc") 这行代码究竟创建了几个对象?
- Stringstr=new String("abc") 这行代码究竟创建了几个对象?
- new String("abc")创建几个对象?
- new String("abc")创建了几个对象
- new String创建了几个对象
- String str=new String("abc");创建几个对象?
- String s=new String("abc")创建了几个对象?
- String s = new String("xyz");创建了几个对象?
- String s=new String("abc")创建了几个对象?
- String str=new String("abc"); 创建了几个对象
- String s = new String("xyz")创建几个对象问题
- String s=new String("abc")创建了几个对象?
- String s = new String( "xyz "); 创建了几个对象?
- 数据上传到服务器的接口
- 使用Git Hooks实现开发部署任务自动化
- 基于Android的串口聊天室 (基于tiny4412) 一
- CentOS7中使用iptables
- Objective-C Runtime 消息机制
- new String()究竟创建几个对象?
- swift 学习笔记(16)-switch 语句
- centos6.4搭建apache+mysql+php环境
- SOAP的接口调用
- 数据库中函数与存储过程的区别
- Fragment提交transaction导致state loss异常
- 添加Commons11个jar,就ok
- CentOS7中systemctl的使用
- 《Objective-C 高级编程》读书笔记之 ARC