深入理解String类详解
1、Stringstr = "eee" 和String str = new String("eee")的区别
先看一小段代码,
1 public static void main(String[] args) {
2 String str1 = "eee";
3 String str2 = "eee";
4 String str3 = new String("eee");
5 System.out.println("str1 == str2 is " + (str1 == str2));
6 System.out.println("str1 == str3 is " + (str1 == str3));
7 System.out.println("str1.equals(str2) is " + str1.equals(str2));
8 System.out.println("str1.equals(str3) is " + str1.equals(str3));
9 }
运行结果为:
str1 == str2 is true
str1 == str3 is false
str1.equals(str2) is true
str1.equals(str3) is true
2、从JVM角度分析
《深入理解Java虚拟机》一书指出,JVM运行时数据区如下:

所有线程共享区域包括:
方法区:用于存储已被虚拟机加载的类信息、常亮、静态变量、即时编译器编译后的代码等数据,以及运行时常量池。
Java堆:在虚拟机启动时创建,存放对象实例,几乎所有的对象实例都在这里分配内存。
线程私有区域包括:
虚拟机栈:用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
本地方法栈:与虚拟机栈类似, 区别主要是本地方法栈为Native方法服务。
程序计数器:一块较小的内存空间,当作当前线程所执行字节码的行号指示器。字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能需要依赖这个计数器来完成。
String是一个不可变对象,可以认为是特殊的常量,因此存在方法区的运行时常量池中,可以被共享使用,以提高效率。
从JVM角度分析以上代码:
1 String str1 = "eee"; //1、在运行时常量池中创建新的对象"eee",如果常量池中不存在的话;2、栈中创建对象的引用str1
2 String str2 = "eee"; //由于运行时常量池中已经存在该对象,直接在栈中创建对象的引用str2即可。
3 String str3 = new String("eee"); //1、通过new指令,在堆中创建新的对象,2、在栈中创建对象的引用str3。
对象之间通过==来比较,比较的是对象的引用。因此也就不难理解为什么str1 == str2, 而str != str3了。
而equals方法比较的是什么呢?如果类没有重写Object类中equals方法时,比较的也就是对象的引用;如果重写了equals方法,那么就要看重写的方法了。
3、从代码角度分析
在jdk1.8中查看String类的源码,
1 public final class String
2 implements java.io.Serializable, Comparable<String>, CharSequence {
3 private final char value[];
4 private int hash; // Default to 0
5
6 public String(String original) {
7 this.value = original.value;
8 this.hash = original.hash;
9 }
10
11 /** 实际比较的是value[]是否相等 */
12 public boolean equals(Object anObject) {
13 if (this == anObject) {
14 return true;
15 }
16 if (anObject instanceof String) {
17 String anotherString = (String)anObject;
18 int n = value.length;
19 if (n == anotherString.value.length) {
20 char v1[] = value;
21 char v2[] = anotherString.value;
22 int i = 0;
23 while (n-- != 0) {
24 if (v1[i] != v2[i])
25 return false;
26 i++;
27 }
28 return true;
29 }
30 }
31 return false;
32 }
33 }
根据源代码可以看出,String类的equals方法比较的实际是value[]是否相等。根据构造函数以及之前的JVM内存模型,可以分析出str1,str2,str3在内存中关系如下:

可以很容易的理解,str1.equals(str3)为true。
4、不建议String对象作为锁去同步
直接看一个例子,
1 public class StringAsSynchronized {
2 public static class Service {
3 public void print(String stringParam) {
4 try {
5 synchronized (stringParam) {
6 while (true) {
7 System.out.print(Thread.currentThread().getName());
8 Thread.sleep(1000);
9 }
10 }
11 } catch (InterruptedException e) {
12 e.printStackTrace();
13 }
14 }
15 }
16
17 public static class ThreadA extends Thread {
18 private Service service;
19 private String stringA = "synchronized";
20
21 public ThreadA(Service service) {
22 this.service = service;
23 }
24
25 @Override
26 public void run() {
27 service.print(stringA);
28 }
29 }
30
31 public static class ThreadB extends Thread {
32 private Service service;
33 private String stringB = "synchronized";
34
35 public ThreadB(Service service) {
36 this.service = service;
37 }
38
39 @Override
40 public void run() {
41 service.print(stringB);
42 }
43 }
44
45 public static void main(String[] args) {
46 Service service = new Service();
47 ThreadA a = new ThreadA(service);
48 a.setName("A");
49 ThreadB b = new ThreadB(service);
50 b.setName("B");
51 a.start();
52 b.start();
53 }
54 }
运行结果为:AAAAAAAAA。。。。
原因为ThreadA类以及ThreadB类中的成员变量stringA以及stringB指向的是同一个对象。
改正方法为
1、第33行修改为private String stringB = new String("synchronized");
2、更好的做法是不使用String对象用来同步锁。
深入理解String类详解的更多相关文章
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- java 复习整理(四 String类详解)
String 类详解 StringBuilder与StringBuffer的功能基本相同,不同之处在于StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此效率上S ...
- STL之string类详解
通过在网站上的资料搜集,得到了很多关于string类用法的文档,通过对这些资料的整理和加入一些自己的代码,就得出了一份比较完整的关于string类函数有哪些和怎样用的文档了!下面先罗列出string类 ...
- Java的String类详解
Java的String类 String类是除了Java的基本类型之外用的最多的类, 甚至用的比基本类型还多. 同样jdk中对Java类也有很多的优化 类的定义 public final class S ...
- Java常用类(一)String类详解
前言 在我们开发中经常会用到很多的常用的工具类,这里做一个总结.他们有很多的方法都是我们经常要用到的.所以我们一定要把它好好的掌握起来! 一.String简介 1.1.String(字符串常量)概述 ...
- Java常用类(二)String类详解
前言 在我们开发中经常会用到很多的常用的工具类,这里做一个总结.他们有很多的方法都是我们经常要用到的.所以我们一定要把它好好的掌握起来! 一.String简介 1.1.String(字符串常量)概述 ...
- std::string类详解
之所以抛弃char*的字符串而选用C++标准程序库中的string类,是因为他和前者比较起来,不必 担心内存是否足够.字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下(甚至 ...
- String类详解(1)
首先String是一个类. 1,实例化String类方法. 1)直接赋值:String name="haha"; 2)通过关键字:String name=new String(&q ...
- String类详解,StringBuffer
先说一下String类的equals()方法. 下面我们先看一段代码: 这段代码输出的结果为: ture true -------------- false 咋看之下貌似Object类比较特别,那么我 ...
随机推荐
- jquery 获取奇数索引的元素,获取复选框,判断是否选中
$(".btn-xs:odd").click(function(){ var $buy_num=$(this).prev("#buy_num").val(); ...
- 类对象序列化为json串,json串反序列化为类对象
1.类对象序列化为json串: 方法一: class P(object): def __init__(self,name,age,sex): self.name=name self.age=age s ...
- c语言单片机中断服务程序
#include <reg52.h> #define uchar unsigned char #define uint unsigned int uint count; void dela ...
- table表格内容溢出处理
直接在table标签加上 style="table-layout:fixed;word-wrap:break-word;"
- SSE图像算法优化系列二十三: 基于value-and-criterion structure 系列滤波器(如Kuwahara,MLV,MCV滤波器)的优化。
基于value-and-criterion structure方式的实现的滤波器在原理上其实比较简单,感觉下面论文中得一段话已经描述的比较清晰了,直接贴英文吧,感觉翻译过来反而失去了原始的韵味了. T ...
- SSE图像算法优化系列二十:一种快速简单而又有效的低照度图像恢复算法。
又有很久没有动笔了,主要是最近没研究什么东西,而且现在主流的趋势都是研究深度学习去了,但自己没这方面的需求,同时也就很少有动力再去看传统算法,今天一个人在家,还是抽空分享一个简单的算法吧. 前段日子在 ...
- Libreoffice 各类文件转换的filtername
LIBREOFFICE_DOC_FAMILIES = [ "TextDocument", "WebDocument", "Spreadsheet&qu ...
- VS2015 ionic 开发环境配置纪要
1)第一次安装Tools for Apache Cordova不成功,到Options检查依赖项,缺少Node等,重新下载了32为的nodeJs安装.然后运行VS安装程序,卸载Tools for Ap ...
- window炫丽cmd的别名cmder
windows下的cmd,色彩度用起来不爽,cmder是对cmd的补充,界面很清爽 01.下载 https://github.com/cmderdev/cmder http://cmder.net/ ...
- php5.6.11编译安装报错configure: error: Don't know how to define struct flock on this system
centos 6.8 32位系统下,安装php.5.6.11是出现这个错误 解决办法: 1 2 3 4 vim /etc/ld.so.conf.d/local.conf # 编辑库文件 /us ...