深入理解String类
1、String str = "eee" 和String str = new String("eee")的区别
先看一小段代码,
public static void main(String[] args) {
String str1 = "eee";
String str2 = "eee";
String str3 = new String("eee");
System.out.println("str1 == str2 is " + (str1 == str2));
System.out.println("str1 == str3 is " + (str1 == str3));
System.out.println("str1.equals(str2) is " + str1.equals(str2));
System.out.println("str1.equals(str3) is " + str1.equals(str3));
}
运行结果为:
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角度分析以上代码:
String str1 = "eee"; //1、在运行时常量池中创建新的对象"eee",如果常量池中不存在的话;2、栈中创建对象的引用str1
String str2 = "eee"; //由于运行时常量池中已经存在该对象,直接在栈中创建对象的引用str2即可。
String str3 = new String("eee"); //1、通过new指令,在堆中创建新的对象,2、在栈中创建对象的引用str3。
对象之间通过==来比较,比较的是对象的引用。因此也就不难理解为什么str1 == str2, 而str != str3了。
而equals方法比较的是什么呢?如果类没有重写Object类中equals方法时,比较的也就是对象的引用;如果重写了equals方法,那么就要看重写的方法了。
3、从代码角度分析
在jdk1.8中查看String类的源码,
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
private final char value[];
private int hash; // Default to 0 public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
/** 实际比较的是value[]是否相等 */
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
}
根据源代码可以看出,String类的equals方法比较的实际是value[]是否相等。根据构造函数以及之前的JVM内存模型,可以分析出str1,str2,str3在内存中关系如下:

可以很容易的理解,str1.equals(str3)为true。
4、不建议String对象作为锁去同步
直接看一个例子,
public class StringAsSynchronized {
public static class Service {
public void print(String stringParam) {
try {
synchronized (stringParam) {
while (true) {
System.out.print(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static class ThreadA extends Thread {
private Service service;
private String stringA = "synchronized";
public ThreadA(Service service) {
this.service = service;
}
@Override
public void run() {
service.print(stringA);
}
}
public static class ThreadB extends Thread {
private Service service;
private String stringB = "synchronized";
public ThreadB(Service service) {
this.service = service;
}
@Override
public void run() {
service.print(stringB);
}
}
public static void main(String[] args) {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
}
}
运行结果为:AAAAAAAAA。。。。
原因为ThreadA类以及ThreadB类中的成员变量stringA以及stringB指向的是同一个对象。
改正方法为
1、第33行修改为private String stringB = new String("synchronized");
2、更好的做法是不使用String对象用来同步锁。
深入理解String类的更多相关文章
- Java基础系列2:深入理解String类
Java基础系列2:深入理解String类 String是Java中最为常用的数据类型之一,也是面试中比较常被问到的基础知识点,本篇就聊聊Java中的String.主要包括如下的五个内容: Strin ...
- 跟着刚哥梳理java知识点——深入理解String类(九)
一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码: public final class String implements java.io.Ser ...
- 深入理解String类详解
1.Stringstr = "eee" 和String str = new String("eee")的区别 先看一小段代码, 1 public static ...
- jdk源码理解-String类
String类的理解 简记录一下对于jdk的学习,做一下记录,会持续补充,不断学习,加油 1.String的hash值的计算方法. hash值的计算方法多种多样,jdk中String的计算方法如下,比 ...
- 【C++】从设计原理来看string类
1.一些C++基础知识 模板类string的设计属于底层,其中运用到了很多C++的编程技巧,比如模板.迭代器.友元.函数和运算符重载.内联等等,为了便于后续理解string类,这里先对涉及到的概念做个 ...
- 从C# String类理解Unicode(UTF8/UTF16)
上一篇博客:从字节理解Unicode(UTF8/UTF16).这次我将从C# code 中再一次阐述上篇博客的内容. C# 代码看UTF8 代码如下: string test = "UTF- ...
- 深入理解Java String类(综合)
在Java语言了中,所有类似“ABC”的字面值,都是String类的实例:String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较.查找.截取.大小写转换等操作:Java语 ...
- String类的深入理解
String不是基本数据类型,String和8种包装类型是不可变类.String和8种基本数据类型采用值传递. 关于方法区中的常量区和class文件中的常量区的关系,参考:https://www.cn ...
- String Buffer和String Builder(String类深入理解)
String在Java里面JDK1.8后它属于一个特殊的类,在创建一个String基本对象的时候,String会向“ 字符串常量池(String constant pool)” 进行检索是否有该数 ...
随机推荐
- Django框架之验证码生成示例
一.生成随机颜色的图片 1)前端代码展示 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- kbmmw 5.04 发布
增加了一大波功能,消灭了一大堆问题,也肯定引进了一大票BUG.We are happy to announce the release of our latest version of kbmMW. ...
- vsftpd只能连接不能上传文件问题
Centos7 记得很清楚,vsftpd安装后,不需要配置,本地用户就可以正常使用(登录.上传.下载) 这次配的就是不行,另起了个虚拟机,装了下,就是不需要配置,但是在一台机上,就是不行,只能登录,下 ...
- poj-3928(树状数组)
题目链接:传送门 题意:n个乒乓球运动员要互相练习,都去一个运动员那里比赛,举办训练的运动员不能水平最高或最低. 现在给出n个运动员的水平,求出最终有多少种组合. 思路:先对运动员进行离散化,然后进行 ...
- Educational Codeforces Round 51 F. The Shortest Statement(lca+最短路)
https://codeforces.com/contest/1051/problem/F 题意 给一个带权联通无向图,n个点,m条边,q个询问,询问两点之间的最短路 其中 m-n<=20,1& ...
- 黑白二值图像周长测量--C#实现
假设是单像素线白色用1(对应RGB(255,0,0))表示,背景用0(对应RBG(0,0,0))表示. 考虑3种类型的边界 水平方向 0->1 1->0 类似垂直方向也是0-> ...
- s7-200 PID控位
只有加热模块,没有风扇,所以温度上冲达到5度左右 TITLE=程序注释 Network // 网络标题 // 初始化 LD SM0. LPS MOVW , VW500 MOVW , VW502 MOV ...
- Win7 VS2017简单编译FFMPEG播放器FFPlay
Win平台简单编译FFPlay播放器,顺便纪念下雷霄骅,一年前刚学FFMPEG时还看过他的博客,昨晚再次搜FFMPEG文章时才知道人已经走了... 做成了视频放到B站 https://www.bili ...
- s5-10 路由
路由器转发分组的依据 路由表 路由表从何而来 直连路由.静态路由.动态路由 路由器收到一个分组之后- 打开分组L3,提取出目的IP地址 确定目标网络,查找路由表 按位"AND&quo ...
- 怎样导入现有的NiosII工程
查找路径