《String的特性》

1、String类是final的,不可被继承。
2、String类是的本质是字符数组char[], 并且其值不可改变。
3、Java运行时会维护一个String Pool(String池),JavaDoc翻译很模糊“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。

String str=new String("abc"); 紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢?

相信大家对这道题并不陌生,答案也是众所周知的,1个或2个。

1 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
2 在字符串常量池中查看,是否存在内容为"abc"字符串对象
3 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
4 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来

接下来我们就从这道题展开,一起回顾一下与创建String对象相关的一些JAVA知识。

我们可以把上面这行代码分成String str、=、"abc"和new String()四部分来看待。String str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;=是对变量str进行初始化,将某个对象的引用赋值给它,显然也没有创建对象;现在只剩下new String("abc")了。那么,new String("abc")为什么又能被看成"abc"和new String()呢?

我们来看一下被我们调用了的String的构造器:
public String(String original) { //other code ... } 大家都知道,我们常用的创建一个类的实例(对象)的方法有以下两种:
一、使用new创建对象。
二、调用Class类的newInstance方法,利用反射机制创建对象。
我们正是使用new调用了String类的上面那个构造器方法创建了一个对象,并将它的引用赋值给了str变量。同时我们注意到,被调用的构造器方法接受的参数也是一个String对象,这个对象正是"abc"。由此我们又要引入另外一种创建String对象的方式的讨论——引号内包含文本。这种方式是String特有的,并且它与new的方式存在很大区别。

String str="abc";
毫无疑问,这行代码创建了一个String对象。

String a="abc"; String b="abc"; 那这里呢?
答案还是一个。

String a="ab"+"cd"; 再看看这里呢?
通过编译器优化后,得到的效果是String a="abcd"
此时,如果字符串常量池中存在abcd,则该语句并不会创建对象,只是讲字符串常量池中的引用返回而已。
如果字符串常量池中不存在abcd,则会创建并放入字符串常量池,并返回引用,此时会有一个对象进行创建。

说到这里,我们就需要引入对字符串池相关知识的回顾了。
在JAVA虚拟机(JVM)中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。由于String类是final的,它的值一经创建就不可改变,因此我们不用担心String对象共享而带来程序的混乱。字符串池由String类维护,我们可以调用intern()方法来访问字符串池。

我们再回头看看String a="abc",这行代码被执行的时候,JAVA虚拟机首先在字符串池中查找是否已经存在了值为"abc"的这么一个对象,它的判断依据是String类equals(Object obj)方法的返回值。如果有,则不再创建新的对象,将使用串池里原来的那个内存,直接返回已存在对象的引用,而不会重新分配内存;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。

而如果用String s=new String("abc"),不管串池里有没有"abc",它都会在堆中重新分配一块内存,定义一个新的对象。
因此我们提倡大家用引号包含文本的方式来创建String对象以提高效率,实际上这也是我们在编程中常采用的。

再看下个例子:

String s="java"+"blog";//直接将javablog对象放入字符串池中。
System.out.println(s=="javablog");//结果是true;

String str1="java";//指向字符串池
String str2="blog";//指向字符串池
String s = str1+str2; // +运算符会在堆中建立起两个String对象,这两个对象的值分别是“java”,"blog",也就是说从字符串常量池中复制这两个值,然后再堆中创建两个对象。然后再建立对象s, 然后将“javablog”的堆地址赋给s. 这句话共创建了3个String对象。
System.out.println(s=="javablog");//因为内存地址不同,结果是false;

String s=str1+"blog";//不放在字符串池中,而是在堆中分分配。
System.out.println(s=="javablog");//结果是false;

JVM对形如String str="java"+"blog";根据编译器合并已知量的优化功能,在池中开辟一块空间,存放合并后的String常量"javablog"。而String s=str1+str2;是在运行时候才能知道的,也就是说str1+str2是在堆里创建的所以结果为false了。

总之,创建字符串有两种方式:两种内存区域(pool,heap)
1.""创建的字符串在字符串池中。
2.new 创建字符串时,首先查看池中是否有相同的字符串,如果有则拷贝一份放到堆中,然后返回堆中的地址;如果池中没有则在堆中创建一份,然后返回堆中的地址,
3.在对字符串赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用。如:String s= str1+"blog";

更多的例子可以看看:http://blog.csdn.net/u010644448/article/details/51980370

java中String s=abc及String s=new String(abc)的区别相关推荐

  1. Java中public,private,protected以及default的访问权限区别

    ** Java中public,private,protected以及default的访问权限区别 ** 首先,从public的字面意思上就能够知道public所指的是公共的,从而我们可以知道publi ...

  2. Java 中访问数据库的步骤?Statement 和PreparedStatement 之间的区别?

    Java 中访问数据库的步骤?Statement 和PreparedStatement 之间的区别? Java 中访问数据库的步骤 1)注册驱动: 2)建立连接: 3)创建Statement: 4)执 ...

  3. Java中WeakReference,SoftReference,PhantomReference和Strong Reference之间的区别

    很长一段时间以来,WeakReference和SoftReference都已添加到Java API中,但是并不是每个Java程序员都熟悉它. 这意味着在Java中使用WeakReference和Sof ...

  4. java中Class对象详解和类名.class, class.forName(), getClass()区别

     一直在想.class和.getClass()的区别,思索良久,有点思绪,然后有网上搜了搜,找到了如下的一篇文章,与大家分享. 原来为就是涉及到Java的反射----- Java反射学习 所谓反射 ...

  5. java中implements是什么意思_Java:extends和implements的区别+用法

    Java代码中的extends和implements让我感到很迷惑,现在终于弄明白它们之间的区别和用法了. //定义一个Runner接口 public inerface Runner { int ID ...

  6. java中操作字符串都有哪些类,他们之间有什么区别?

    java中操作字符串的类有哪些? String StringBuffer StringBuilder 区别 我们可以先看一下这几个类的继承关系图 从类的继承关系上来开的话,String和StringB ...

  7. Java中字符串以小数点分割时无效,String s = “12.34“; String[] ss = split(“.“);分割结果为空

    String s = "12.34"; String[] ss = split("."); //输出结果ss为null 解决:小数点 . 是正则表达式中特殊标记 ...

  8. java中实现同步的两种方式:syschronized和lock的区别和联系

    转载自 http://www.cnblogs.com/xiohao/p/4151408.html Lock是java.util.concurrent.locks包下的接口,Lock 实现提供了比使用s ...

  9. Java中正则Matcher类的matches()、lookAt()和find()的区别

    在Matcher类中有matches.lookingAt和find都是匹配目标的方法,但容易混淆,整理它们的区别如下: matches:整个匹配,只有整个字符序列完全匹配成功,才返回True,否则返回 ...

  10. JAVA中自增自减运算符(i++与++i的区别)

    注意: 自增运算符和自减运算符只能用于变量,而不能用于常亮或表达式 运算符 运算 范例 结果 ++ 自增(前):先运算后取值 a=2;b=++a; a=3;b=3; ++ 自增(后):先取值后运算 a ...

最新文章

  1. Python matplotlib 绘制量场图
  2. 谷歌、OpenAI等警告:BERT、GPT-3等大型语言模型都有一个重大缺陷,很危险...
  3. Pandas (GeoPandas)笔记:set_index reset_index
  4. static 关键字静态导包
  5. 沉默已久的华为突然宣告杀入无人驾驶领域,司机将全部失业!
  6. java nlpir_4-NLPIR汉语分词系统-JAVA
  7. web开发中不同设备浏览器的区分
  8. Linux操作命令(二)
  9. Springboot Excle导入导出
  10. 程序人生-Hello的 P2P
  11. 语音信号处理-概念(二):幅度谱(短时傅里叶变换谱/STFT spectrum)、梅尔谱(Mel spectrum)【语音的深度学习主要用幅度谱、梅尔谱】【用librosa或torchaudio提取】
  12. FBX模型格式和FbxSDK
  13. 微信授权 昵称显示微信用户、无头像
  14. 把网页知乎的视频下载下来
  15. Matplotlib 绘制折线图 - 正余弦函数图像
  16. Stata: 面板 Granger 因果检验
  17. 陈于冰的二三四五业绩腰斩,去金融化“裸泳”
  18. C语言mplayer项目凌阳爱普,C语言控制mplayer
  19. Unicode对汉字的编码 1
  20. [FRM] FRM notes|FRM电子教材|FRM教材

热门文章

  1. 计算机睡眠模式游戏开着,计算机睡眠
  2. Linux产生序列数字
  3. macbook android截屏,配合Alfred的mac端自动截图脚本(ios android适用)
  4. yum与apt的区别
  5. C2. Tidying Up(费用流 二分图)
  6. 防照骗!Adobe 新 AI 工具,还原被 P 过的脸
  7. 多人访问亚马逊后台-用户权限设置
  8. 算法(八)分枝-限界法
  9. matlab图像处理英文文献,matlab图像处理中英文翻译文献
  10. 最新神经网络论文推荐,最新神经网络图像渲染