Java中的String问题
方式一:String a = “aaa” ;
方式二:String b = new String(“aaa”);
两种方式都能创建字符串对象,但方式一要比方式二更优。
因为字符串是保存在常量池中的,而通过new创建的对象会存放在堆内存中。
一:常量池中已经有字符串常量”aaa”
通过方式一创建对象,程序运行时会在常量池中查找”aaa”字符串,将找到的”aaa”字符串的地址赋给a。
通过方式二创建对象,无论常量池中有没有”aaa”字符串,程序都会在堆内存中开辟一片新空间存放新对象。
一:常量池中没有字符串常量”aaa”
通过方式一创建对象,程序运行时会将”aaa”字符串放进常量池,再将其地址赋给a。
通过方式二创建对象,程序会在堆内存中开辟一片新空间存放新对象,同时会将”aaa”字符串放入常量池,相当于创建了两个对象。
测试:
String a = "aaa";
String b = "aaa";
String c = new String("aaa"); System.out.println(a == b); //比较地址a,b相等
System.out.println(a == c); //比较地址a,c不等
System.out.println(a.equals(c));//equals比较内容相等
结果:
a==b:true
a==c:false
a与b的值相等:true
http://talentluke.iteye.com/blog/1539870
public class Test {
public static void main(String[] args) {
String str = "abc";
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str == str1); //true
System.out.println(str1 == "abc"); //true
System.out.println(str2 == "abc"); //false
System.out.println(str1 == str2); //false
System.out.println(str1.equals(str2)); //true
System.out.println(str1 == str2.intern()); //true
System.out.println(str2 == str2.intern()); //false
System.out.println(str1.hashCode() == str2.hashCode()); //true
}
}
堆(heap)内存和栈(Stack)内存的问题。堆和栈的数据结构这里就不解释了。Java语言使用内存的时候,栈内存主要保存以下内容:基本数据类型和对象的引用,而堆内存存储对象,栈内存的速度要快于堆内存。总结成一句话就是:引用在栈而对象在堆。
使用String时可以直接赋值,也可以用new来创建对象,但是这二者的实现机制是不同的。还有一个String池的概念,Java运行时维护一个String池,池中的String对象不可重复,没有创建,有则作罢。String池不属于堆和栈,而是属于常量池。
这个是Java SE的热点问题,众所周知,单独这句话创建了2个String对象,而基于上面两句,只在栈内存创建str2引用,在堆内存上创建一个String对象,内容是”abc”,而str2指向堆内存对象的首地址。
下面就是str2==”abc”的问题了,显然不对,”abc”是位于String池中的对象,而str2指向的是堆内存的String对象,==判断的是地址,肯定不等了。
str1.equals(str2),这个是对的,前面说过,String类的equals重写了Object类的equals()方法,实际就是判断内容是否相同了。
下面说下intern()方法,在JavaDoc文档中,这样描述了intern()方法:返回字符串对象的规范化表示形式。怎么理解这句话?实际上过程是这样进行的:该方法现在String池中查找是否存在一个对象,存在了就返回String池中对象的引用。
那么本例中String池存在”abc”,则调用intern()方法时返回的是池中”abc”对象引用,那么和str/str1都是等同的,和str2就不同了,因为str2指向的是堆内存。
hashCode()方法是返回字符串内容的哈希码,既然内容相同,哈希码必然相同,那他们就相等了,这个容易理解。
public class Test {
private static String str = "abc";
public static void main(String[] args) {
String str1 = "a";
String str2 = "bc";
String combo = str1 + str2;
System.out.println(str == combo);
System.out.println(str == combo.intern());
}
}
这个例子用来说明用+连接字符串时,实际上是在堆内容创建对象,那么combo指向的是堆内存存储”abc”字符串的空间首地址,显然str==combo是错误的,而str==combo.intern()是正确的,在String池中也存在”abc”,那就直接返回了,而str也是指向String池中的”abc”对象的。此例说明任何重新修改String都是重新分配内存空间,这就使得String对象之间互不干扰。也就是String中的内容一旦生成不可改变,直至生成新的对象。
同时问题也来了,使用+连接字符串每次都生成新的对象,而且是在堆内存上进行,而堆内存速度比较慢(相对而言),那么再大量连接字符串时直接+是不可取的,当然需要一种效率高的方法。Java提供的StringBuffer和StringBuilder就是解决这个问题的。区别是前者是线程安全的而后者是非线程安全的,StringBuilder在JDK1.5之后才有。不保证安全的StringBuilder有比StringBuffer更高的效率。
自JDK1.5之后,Java虚拟机执行字符串的+操作时,内部实现也是StringBuilder,之前采用StringBuffer实现。
Java中的String问题的更多相关文章
- 再解java中的String
今天看到一篇文章中,写了关于java中的String.我看了后,是我从学java来觉得是最好的一篇关于String类的文章.看了这篇文章你就会对String的认识会提高一个层次.故将原作者的文章特意转 ...
- (转)Java中的String为什么是不可变的
转自:http://www.importnew.com/7440.html String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了 ...
- 关于JAVA中的String的使用与连接(转)
JAVA中的String连接性能 Java中的String是一个非常特殊的类,使它特殊的一个主要原因是:String是不可变的(immutable). String的不可变性是Ja ...
- Java中的String为什么是不可变的?
转载:http://blog.csdn.net/zhangjg_blog/article/details/18319521 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那 ...
- Java中的String与常量池[转帖]
string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象.下面介绍java中的String与常量池. 1. 首先String不属于8种 ...
- Java中的String与常量池
string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象.下面介绍java中的String与常量池. 1. 首先String不属于8种 ...
- java中字符串String 转 int(转)
java中字符串String 转 int String -> int s="12345"; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法 ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- Java中的String,StringBuilder,StringBuffer三者的区别
最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下, ...
- Java中的String,StringBuilder,StringBuffer三者的区别(转载)
最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下, ...
随机推荐
- 广二模拟赛 Problem A: 青春野狼不做理性小魔女的梦 解题报告
Problem A: 青春野狼不做理性小魔女的梦 题意 给一个长为\(k\)的序列\(A\)和一个数\(n\),给出一部分\(A_i\)的值,另一部分为\(-1\),代表不知道这个\(A_i\)是多少 ...
- postgresql常见命令及操作
pgsql已经更新到beta11了,不同版本的服务器启动或相关命令.配置可能会有不同,所以得根据pg版本进行操作.下面记录一些工作中常用到的一些操作,主要包括服务启动.备份/恢复数据.数据目录迁移.常 ...
- linux命令总结mpstat命令
简介 mpstat是Multiprocessor Statistics的缩写,是实时系统监控工具.其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中.在多CPUs系统里,其不但能查 ...
- 【转载】视频CDN技术原理与流程说明
视频CDN专为移动互联网视频内容分发量身定做的一套自主研发的分布式平台,该平台以深圳为中心,分布在全国各地BGP机房的服务器为边缘节点,汇聚中国电信.中国联通.中国移动.中国教育网等运营商网络资源,构 ...
- spring中bean配置和注入场景分析
bean与spring容器的关系 Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载.实例化Bean,并 ...
- 20155339 2016-2017-2 《Java程序设计》第5周学习总结
20155339 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 使用try.catch 使用try.catch语法,JVM会先尝试执行try区块中的代码,如 ...
- shell 循环数组
循环数组 ;i<${#o[*]};i++)) do echo ${o[$i]} done
- CSS float浅析
写在开篇: 浮动属性的设计初衷,只是为了实现文本环绕效果! 时刻牢记这一点,才能正确使用浮动. 由于浮动元素脱离文档流,它后面的块级元素会忽略它的存在,占据它原本的位置,但是这个块级元素中的内联元素, ...
- oracel 复制A列的内容到列
update jieguo1 t set t.chinesetablename =t.tablezhushi where length(t.chinesetablename) >= 15 and ...
- 第一篇:初始Golang
Golang简介 编程语言已经非常多,偏性能敏感的编译型语言有 C.C++.Java.C#.Delphi和Objective-C 等,偏快速业务开发的动态解析型语言有PHP.Python.Perl.R ...