java字符串常量池——字符串==比较的一个误区
转自:https://blog.csdn.net/wxz980927155/article/details/81712342
起因
再一次js的json对象的比较中,发现相同内容的json对象使用==比较并不相等。
例如:
var obj = {};
var obj2 = {};
console.log(obj == obj2); // 结果为false
json在js中代表一个对象==比较的是对象栈中存放引用堆的地址。上面的obj和obj2创建的是两个对象地址肯定不同结果为false。
但最令我不解的是为什么js的字符串比较可以用==来比较字符串的内容是否相等,而java却要使用equals去比较字符串的内容是否相等。但当我发现下面代码的时候又刷新了我这个菜鸟的认知。
String str1 = "test";
String str2 = "test";
System.out.println(str1 == str2); // 结果为true
结果难道不该为false吗?字符串的比较难道不是用equals来比较内容是否相等吗?两个不同的对象创建的内存地址应该是不一样的啊!!后来经过网上查阅资料发现jvm还存在一个字符串常量池。
字符串常量池
让我们先分析一下上述的代码:
在我的理解中常量池应该是为了减少开发者对字符串过度的创建,导致内存使用率的提升,毕竟String类是一个final类,操作字符串永远不会改变当前字符串的值,只会新增一个字符串对象。
String str1 = "test";
/* jvm在编译的时候会先查看str1字面量test是否存放在字符串常量池中有则直
接引用字符串常量池里面的地址,没有则在字符串常量池新创建一个*/
String str2 = "test";
/* str2发现字符串常量池里面已经有了test则直接把字符串常量池里面的地址拿
了过来*/
System.out.println(str1 == str2);
// 最终str1和str2的地址都是相同的结果肯定为true啦
既然都到这里在拓展拓展在走呗
String str1 = new String("test");
String str2 = new String("test");
System.out.println(str1 == str2); // 结果为false
// 这个为什么不为true了呢?
new String()会在代码运行的时候在堆中开辟一个空间存放引用字符串常量池里面的地址但是栈里面引用的堆的地址是不一样的,所以即使引用的字符串常量池里面的地址是一样也永远不可能为true!!
intern方法
强制String对象使用字符串常量池
String str1 = new String("test");
String str2 = new String("test");
str1 = str1.intern();
str2 = str2.intern();
System.out.println(str1 == str2); // 结果为true
经典面试题
String str1 = new String("test");
// 此代码执行会创建几个对象?
// A:1个或2个,堆中会创建一个,字符串常量池中有test则常量池中不会创建,没有则创建
总结
字符串字面量会在编译的就开始判断是否在字符串常量池里面创建,而new String()会在代码运行的时候才去判断。
字符串常量池里面没有此字符串则会创建,有则会去引用字符串常量池里面的字符串。字面量里字符串常量池的地址存放在栈中,new String()则存放在堆中。
java字符串常量池——字符串==比较的一个误区的更多相关文章
- Knowledge Point 20180309 字符串常量池与String,intern()
引言 什么都先不说,先看下面这个引入的例子: public static void test4(){ String str1 = new String("SEU") + new S ...
- 8.StringTable(字符串常量池)
一.String的基本特性 String:字符串,使用一对 "" 引起来表示 String s1 = "atguigu" ; // 字面量的定义方式 Strin ...
- 彻底搞清楚class常量池、运行时常量池、字符串常量池
彻底搞清楚class常量池.运行时常量池.字符串常量池 常量池-静态常量池 也叫 class文件常量池,主要存放编译期生成的各种字面量(Literal)和符号引用(Symbolic Reference ...
- java基础知识回顾之---java String final类 容易混淆的java String常量池内存分析
/** * 栈(Stack) :存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放 在常量池中). 堆(heap):存 ...
- Java字符串常量池
JVM为了减少字符串对象的重复创建,维护了一个特殊的内存,这段内存被称为字符串常量池. Java中字符串对象的创建有两种形式:一种是字面量形式,String str = "a":一 ...
- Java中的字符串常量池
ava中字符串对象创建有两种形式,一种为字面量形式,如String str = "droid";,另一种就是使用new这种标准的构造对象的方法,如String str = new ...
- Java中String字符串常量池总结
最近到广州某建站互联网公司面试,当时面试官问假设有两个字符串String a="abc",String b = "abc";问输出a==b是true还是fals ...
- java中字符串“不可变性”的破坏,使用反射破坏final属性。以及涉及到字符串常量池的问题。
大家都清楚java中String类是不可变的,它的定义中包含final关键字.一旦被创建,值就不能被改变(引用是可以改变的). 但这种“不可变性”不是完全可靠的,可以通过反射机制破坏.参考一下代码: ...
- Java中String字符串常量池
首先看一个例子,通过这个例子更能快速理解String常量池 public static void main(String[] args) { String a = "ab"; St ...
随机推荐
- Android:防止过快点击造成多次事件 问题
自定义一个NoDoubleClickListener,继承自OnClickListener: public abstract class NoDoubleClickListener implement ...
- (转)Makefile介绍
2. Makefile介绍 make命令执行时,需要一个Makefile文件,以告诉make命令需要怎么样的去编译和链接程序. 首先,我们用一个示例来说明Makefile的书写规则.以便给大家一个感性 ...
- 使用UtraISO为U盘制作系统启动盘
安装最新的Ubuntu18.04操作系统: 1.在utraiso软件中打开系统的iso文件: 2.插入U盘: 3.点击[启动]选项卡,选择[写入硬盘映像]: 4.最关键的一步: 刻录校验:打上对勾: ...
- servlet和jsp概述
1.servlet的作用 B/S系统:浏览器/服务器(Servlet的服务模式) Servlet是运行在web服务器或应用服务器上的java程序,它是一个中间层,负责连接来自web浏览器或其它HTTP ...
- Don't afraid point
int p; int *p; int p[3]; int *p[3];分析方式:首先从P开始分析,先与[]结合因为其优先级比*高,所以p是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与 ...
- CS229 7.2 应用机器学习方法的技巧,准确率,召回率与 F值
建立模型 当使用机器学习的方法来解决问题时,比如垃圾邮件分类等,一般的步骤是这样的: 1)从一个简单的算法入手这样可以很快的实现这个算法,并且可以在交叉验证集上进行测试: 2)画学习曲线以决定是否更多 ...
- Solr——Windows下部署Solr6.6.0至Tomcat8.5.28(一)
一.window 环境 solr 6.6.3 下载地址 http://archive.apache.org/dist/lucene/solr/ jdk 1.8 tomcat 8.5 本机tomc ...
- 使用bootstrap3.0搭建一个具有自定义风格的侧边导航栏
由于工作变动,新的项目组,可能会涉及到更多的类似于后台管理系统这一类的项目,而且开发可能更加偏向于传统型的开发,希望今后能够在新的项目中能够用得上vuejs吧! 接手项目的时候,就是一个后台管理系统, ...
- (转)处理SQL中的异常并记录错误日志
原文地址 创建错误日志表: ),ErrState ),ErrLine )) --创建错误日志记录存储过程: CREATE PROCEDURE ErrorLog AS SELECT ERROR_NUMB ...
- 《机器学习实战》AdaBoost算法(手稿+代码)
Adaboost:多个弱分类器组成一个强分类器,按照每个弱分类器的作用大小给予不同的权重 一.Adaboost理论部分 1.1 adaboost运行过程 注释:算法是利用指数函数降低误差,运行过程通过 ...