java运行环境有一个字符串池。比如String str="abc"时,会首先查看字符串池中是否存在字符串"abc",如果存在则直接将"abc"赋给str,如果不存在则会先在字符串池中新建一个字符串"abc",然后再将其赋给str。如果执行代码
String str1="abc"; String str2="abc"; System.out.println(str1==str2);
则这段代码结果就会是true。执行str1时,会首先检查字符串池中是否存在"abc",如果有则直接赋给str1,如果没有则在字符串池中创建一个"abc"然后再赋给str1,当执行到str2时,检查字符串池已经存在了"abc",因此直接赋给str2,str1与str2指向同一个对象,所以结果为true。
而执行String str=new String("abc")时,不管字符串池中有没有"abc"都会在堆中新建一个字符串对象然后将其赋给str引用。所以执行如下代码
- String str1=new String("abc");
- String str2=new String("abc");
- System.out.println(str1==str2);
String str1=new String("abc"); String str2=new String("abc"); System.out.println(str1==str2);
结果就会为false,因为str1与str2指向的分别是两个不同的对象。
- String str1="abc";
- String str2="def";
- String str3=str1+str2;
- System.out.println(str3=="abcdef");
- //结果肯定是为false
String str1="abc"; String str2="def"; String str3=str1+str2; System.out.println(str3=="abcdef"); //结果肯定是为false
因为str3指向堆中的"abcdef"对象,而"abcdef"是字符串池中的对象,因为结果为false。JVM对String str="abc"对象放在常量池中是在编译时做的,而String str3=str1+str2是在运行时刻才能知道的。new对象也是在运行时才做的。而这段代码总共创建了5个对象,字符串池中两个、堆中三个。+运算符会在堆中建立来两个String对象,也就是说从字符串池中复制这两个值,然后在堆中创建两个对象,然后再建立对象str3,然后将"abcdef"的堆地址赋给str3。
而如果
- String str="abc"+"def"; //直接将"abcdef"放入字符串池中
- System.out.println(str=="abcdef");
- //结果为true
- String str1="abc";
- String str2=str1+"def"; //str1是在堆中创建的对象
- System.out.println(str2=="abcdef");
- //结果为false
String str="abc"+"def"; //直接将"abcdef"放入字符串池中 System.out.println(str=="abcdef"); //结果为true String str1="abc"; String str2=str1+"def"; //str1是在堆中创建的对象 System.out.println(str2=="abcdef"); //结果为false
由于字符串对象的大量使用(它是一个对象,一般而言对象总是在堆中分配内存),Java中为了节省内存空间和运行时间(如比较字符串时,==比equals()快),在编译阶段就把所有的字符串文字放到一个字符串池中,而运行时字符串池成为常量池的一部分。字符串池的好处,就是该池中所有相同的字符串常量被合并,只占用一个空间。
我们知道,对两个引用变量,使用==判断它们的值(引用)是否相等,即指向同一个对象:
String s1 = "abc" ;
String s2 = "abc" ;
if( s1 == s2 ) System.out.println("s1,s2 refer to the same object");
else System.out.println("trouble");
这里的输出显示,两个字符串文字保存为一个对象。就是说,上面的代码只在字符串中创建了一个String对象。
现在看String s = new String("abc");语句,这里"abc"本身就是pool中的一个对象,而在运行时执行new String()时,将字符串池中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有。ok,这条语句就创建了2个String对象。
String s1 = new String("abc") ;
String s2 = new String("abc") ;
if( s1 == s2 ){ //不会执行的语句}
这时用==判断就可知,虽然两个对象的"内容"相同(equals()判断),但两个引用变量所持有的引用不同,上面的代码创建了几个String 对象? (3个,字符串池中1个,堆中2个。)
创建字符串有两种方式:两种内存区域(字符串池,堆)
1," " 引号创建的字符串在字符串池中
2,new,new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则导致浪费池的空间)
另外,对字符串进行赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用;如String str2=str1+ "abc";
比较两个已经存在于字符串池中字符串对象可以用"=="进行,拥有比equals操作符更快的速度。
发表评论
-
test
2015-11-02 13:16 527testestsetet -
java thread : select poll epoll
2015-02-16 16:42 1236Select/Poll函数 Selec()的3 ... -
java thread : IO模型
2015-02-16 15:33 916IO复用:select和poll函数 ... -
ssoYY: sso的跨域问题
2015-02-06 10:52 0dsfdsfsd -
交互的YY: 交互 解耦 关系 规则
2015-01-25 15:58 1191交互需要什么:对象,对象之间是怎么交互的(直接new 注入还 ... -
java thread : NIO -概念
2015-01-22 16:04 675通道-流:代表一种功能,能操作数据的方法(策略) 数据来 ... -
ThreadLocal 简单分析
2015-01-09 15:21 761ThreadLocal<T> 是一 ... -
java 多核理解
2014-11-18 13:10 835多核、超线程CPU时代 ... -
java_thread 隐藏的迭代器 java并发编程实践
2014-04-28 10:06 10535.1.3 隐藏迭代器 看容器源代码更清楚些 ... -
笔记1 java并发编程实践
2014-04-25 16:19 562同步 共享(shared)(多个线程访问)和可变(mutabl ... -
java_thread interrupt 理解
2014-04-25 13:18 917package com.java.util.con ... -
超越java-此书笔记
2012-12-24 15:23 902前言: SSH所带来的烦恼:重复的事情太多、XML配 ... -
字符集和字符编码
2012-12-20 19:58 8140. 字符 :大家平时看 ... -
为什么heap分配和清理内存可能会比栈的存储分配慢?
2012-06-12 12:49 0。。。。。。。。 -
泛型PS
2012-05-13 19:24 9501.使用泛型的时候,如果2边都使用了泛型,则2边必须一样// ... -
java中PS的几点
2012-05-13 18:33 10601.增强for循环只能取数 ... -
在java switch中使用String作为分支条件 (转)
2012-05-13 16:26 2283在java中明确规定switch里面只允许使用int,ch ...
相关推荐
- **问题**:如何将一个整型数字转换为字符串,例如将 `Integer` 和 `Double` 转换为字符串。 - **解释**:可以使用 `Integer.toString()` 或者 `Double.toString()` 方法来进行转换。这些方法会将指定的整数或...
首先,公共资源模块的设计应遵循模块化原则,将不同的资源类型(如配置文件、图片、音频、数据库连接字符串等)进行分类和封装,以便于管理和调用。在这个项目中,我们可以看到开发者可能采用了接口和抽象类来定义...
- **反转字符串**:可以通过循环遍历字符串并从后向前构建新字符串来实现。 ```java public String reverse(String s) { StringBuilder sb = new StringBuilder(s); return sb.reverse().toString(); } ``` - ...
2. **公共资源**:公共资源通常包括常量、配置文件、国际化字符串、静态工具类等,它们被多个模块或组件共享。合理设计公共资源模块可以减少代码重复,提供统一的访问接口,并方便后期维护。 3. **接口与实现分离**...
- `intern`、常量池: 字符串的优化手段。 - `StringBuffer`: 字符串拼接的高效方式。 - `java.util.Date`、`SimpleDateFormat`: 日期和时间的操作。 - `Regex` (正则表达式): 字符串匹配。 - **反射机制** - `...
81 话题14 井然有序——运算顺序的详细挖掘 86 话题15 异曲同工——交换变量的3种方式 90 话题16 择木而栖——开关选择表达式switch的类型内幕 95 第3章 String类 103 话题17 来龙去脉——“+”是怎样连接字符串的?...
- 将 GB2312 编码的字符串转换为 ISO-8859-1 编码:使用 `String.getBytes("GB2312")` 转为字节数组,然后使用 `new String(bytes, "ISO-8859-1")` 转换回字符串。 9. **Java中访问数据库** - 使用 JDBC 连接...
- **数值型字符转数字**:可以使用`Character.getNumericValue(char)`方法或者通过`Integer.parseInt(String)`和`Double.parseDouble(String)`等方法将字符串转换为数值。 - **数字转字符**:使用`Character....
5. **十进制转十六进制程序**:利用递归或循环算法将整数转换为十六进制字符串表示。 6. **SQL统计查询**:使用CASE WHEN THEN语句结合GROUP BY和COUNT函数完成复杂的聚合统计。 7. **火车速度问题**:通过建立数学...
- 字符串反转:可以通过将字符串转化为字符数组,再反转数组的方式来实现。 - 字符串替换:使用`replace`或`replaceAll`方法来完成特定字符或模式的替换。 3. **数据类型之间的转换**: - 数值型字符转数字:...
例如,程序输出的"true"表示两个对象实例化后引用的String对象指向的是同一个内存地址,即它们是同一个字符串对象。输出的"22"表明在Test类的两个不同对象中,静态变量b的值都是2。 整个Java对象创建过程涉及到内存...
- **反转字符串**:可以使用StringBuilder或StringBuffer的reverse()方法。 - **替换字符串**:使用String类的replace()或replaceAll()方法。 #### 3. 数据类型之间的转换 - **数值型字符转数字**:使用Integer....
- 字符串反转可以通过将字符串转换为字符数组,再利用循环来实现。 - 字符串替换可以使用`replace`或`replaceAll`方法。 3. **数据类型之间的转换**: - 将数值型字符转换为数字:使用`Character....
表达式则会将Java表达式的值转换为字符串并插入到输出流中。 4. **JSP内置对象**:JSP提供了一系列内置对象,如`request`、`response`、`session`和`application`等,它们简化了HTTP请求和响应的处理,以及会话和...
第5章数组与字符串200 5.1数组200 5.1.1一维数组的声明200 5.1.2一维数组的创建201 5.1.3一维数组的使用202 5.1.4二维数组的声明204 5.1.5二维数组的创建205 5.1.6二维数组的使用207 5.1.7for~each循环208 ...