方式一: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问题的更多相关文章

  1. 再解java中的String

    今天看到一篇文章中,写了关于java中的String.我看了后,是我从学java来觉得是最好的一篇关于String类的文章.看了这篇文章你就会对String的认识会提高一个层次.故将原作者的文章特意转 ...

  2. (转)Java中的String为什么是不可变的

    转自:http://www.importnew.com/7440.html String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了 ...

  3. 关于JAVA中的String的使用与连接(转)

    JAVA中的String连接性能 Java中的String是一个非常特殊的类,使它特殊的一个主要原因是:String是不可变的(immutable).           String的不可变性是Ja ...

  4. Java中的String为什么是不可变的?

    转载:http://blog.csdn.net/zhangjg_blog/article/details/18319521 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那 ...

  5. Java中的String与常量池[转帖]

    string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象.下面介绍java中的String与常量池. 1. 首先String不属于8种 ...

  6. Java中的String与常量池

    string是java中的字符串.String类是不可变的,对String类的任何改变,都是返回一个新的String类对象.下面介绍java中的String与常量池. 1. 首先String不属于8种 ...

  7. java中字符串String 转 int(转)

    java中字符串String 转 int String -> int s="12345"; int i; 第一种方法:i=Integer.parseInt(s); 第二种方法 ...

  8. Java基础知识强化101:Java 中的 String对象真的不可变吗 ?

    1. 什么是不可变对象?       众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...

  9. Java中的String,StringBuilder,StringBuffer三者的区别

    最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下, ...

  10. Java中的String,StringBuilder,StringBuffer三者的区别(转载)

    最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下, ...

随机推荐

  1. MySQL索引类型,优化,使用数据结构

    工欲善其事必先利其器 半藏说道:“若你在路途中遇到上帝,上帝也会被割伤.” 一.mysql 索引分类(默认使用B树结构)在数据库表中,对字段建立索引可以大大提高查询速度.通过善用这些索引,可以令 My ...

  2. 洛谷SP16580 QTREE7 - Query on a tree VII(LCT,multiset)

    洛谷题目传送门 思路分析 维护子树最值还是第一次写QwQ 因为子树的最值会变化,所以不能简单地把最值记下来,还要维护一个平衡树,把每个子树的最大值扔进去,来资磁插入.删除和查询最值. 然后我就懒得手写 ...

  3. 自学Zabbix3.5.3-监控项item-zabbix agent 类型所有key

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 1. 温习       Zabbix server是Zabbix软件的中心进程. Server执行 ...

  4. Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算)

    Libre 6009 「网络流 24 题」软件补丁 / Luogu 2761 软件安装问题 (最短路径,位运算) Description T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放 ...

  5. linux socat命令

    http://note.youdao.com/noteshare?id=35901183d9ccc09632339ec971fa58dd

  6. Ansible Role

    Ansible Role 专题总揽 https://www.jianshu.com/p/1be92c3f65ec lework 关注 2017.03.02 12:57* 字数 629 阅读 1439评 ...

  7. package.json浅谈

    相信很多小伙伴都见过各种各样的Node.js项目,而里面都有一个名为package.json的文件,而这个文件究竟是干什么的呢? 简单的来说,这个文件就是对整个项目的各种情况的配置(也是介绍),下面给 ...

  8. CF #442 div2

    A 判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人.. /** @Date : 2017-10-24 16:04:41 * @FileName: A.cpp * @P ...

  9. Linux使用imagemagick的convert命令压缩图片、节省服务器空间

    一.安装: sudo apt-get install imagemagick 二.说明 imagemagick的命令convert可以完成此任务,其参数-resize用来改变图片尺寸,可以直接指定像素 ...

  10. Kafka 温故(四):Kafka的安装

    Step 1: 下载Kafka > tar -xzf kafka_2.9.2-0.8.1.1.tgz> cd kafka_2.9.2-0.8.1.1 Step 2: 启动服务Kafka用到 ...