String的Equals()和==比较

  常量池(Constant Pool):指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。JVM虚拟机为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(String,Integer和 Floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的, 对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。

  1、String s = "abc"; 

  创建过程分析:在class文件被JVM装载到内存中,JVM会创建一块String Pool(String缓冲池)。当执行String s = “abc”;时,JVM首先在String Pool中查看是否存在字符串对象“abc”(如何查看呢?用equals()方法判断),如果已存在该对象,则不用创建新的字符串对象“abc”,而直接使用String Pool中已存在的对象“abc”,然后将引用s指向该对象;如果不存在该对象,则先在String Pool中创建一个新的字符串对象“abc”,然后将引用s指向String Pool中创建的新对象。 

  注意:使用“字符串常量”引号创建的字符串对象时,在编译期就已经确定将该对象存储到String Pool中了。因此,String s = “abc”只会在编译期,在String Pool中创建一个对象。

  2、String s = new String("abc"); 

  创建过程分析:当执行String s = new String(“abc”);时,JVM首先在String Pool中查看是否存在字符串对象“abc”,如果不存在该对象,则先在String Pool中创建一个新的字符串对象“abc”,然后执行new String(“abc”)构造方法,在Heap里又创建一个新的字符串对象“abc”(new出来的对象都放在Heap里面),并将引用s指向Heap中创建的新对象;如果已存在该对象,则不用创建新的字符串对象“abc”,而直接使用String Pool中已存在的对象“abc”, 然后执行new String(“abc”)构造方法,在Heap里又创建一个新的字符串对象“abc”,并将引用s指向Heap中创建的新对象。 

  注意:使用new String(“”)创建的字符串对象时,会在运行期创建新对象存储到Heap中。因此,new String(“abc”)创建字符串对象时,会创建2个对象,编译期在String Pool中创建一个,运行时Heap中创建一个。

示例代码:

  

String a="hello"; //编译期间,以被存储字符串常量池
String b=new String("hello"); //运行期间才会创建
final String c="hello"; //编译期间已被存储字符串常量池
String d="hel";
String e="lo";
String f=new String("lo");
System.out.println(a==b); //false
System.out.println(a.equals(b)); //true
System.out.println(a==c); //true
System.out.println(a.equals(c)); //true
System.out.println(b==c); //false
System.out.println(b.equals(c)); //true
System.out.println("******split*****");
System.out.println(a==(d+f)); //false
System.out.println(a.equals(d+f)); //true
System.out.println(c==(d+f)); //false
System.out.println(c.equals(d+f)); //true

注意代码:

  1、对于有+号,并且有引用变量:

  

String s1 = "abc";
String s2 = "def";
String s3 = "abcdef";
String s4 = "abc"+"def";
String s5 = s1 + "def";
String s6 = "abc"+s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s3 == s7);
  运行结果如下:
  true
  false
  false
  false
  
结果说明:JVM对于有字符串引用存在的字符串"+"连接中,而引用的值在程序编译期是无法确定的,即s1 + “def”无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给s5。 但是对于强制声明为final的除外,如下所示:
final String s1 = "abc";
final String s2 = "def";
String s3 = "abcdef";
String s4 = "abc"+"def";
String s5 = s1 + "def";
String s6 = "abc"+s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
System.out.println(s3 == s6);
System.out.println(s3 == s7);

运行结果如下: 
true 
true 
true 
true 

结果说明
:例程3和例程4与例程2的区别是,例程3在字符串s1前加了final修饰,例程4在字符串s1和s2前都加了final修饰。对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的s1 + “def”和"abc" + "def"效果是一样的。接着后面两个含引用的字符串连接,JVM会进行相同的处理。故上面程序后面三个的结果为true。 
2、对于方法调用的
public static void main(String args[]){
String s1 = "abc";
final String s2 = getDef();
String s3 = "abcdef";
String s4 = "abc"+s2;
String s5 = s1 + s2;
System.out.println(s3 == s4);
System.out.println(s3 == s5);
} private static String getDef(){
return "def";
} 程序运行结果如下:
false
false
结果说明:JVM对于方法调用给字符串引用赋值的情况,引用指向字符串的值在编译期是无法确定的,只有在程序运行调用方法后,将方法的返回值“def”和“abc”动态连接并分配新地址赋值给s4,所以上述程序的结果都为false。

String s=new String("XYZ")+new String("XYZ");总共创建了四个对象

对于第一个new String("XYZ"),需要在StringPool中存储XYZ创建一个对象,构造函数创建一个对象

对于第二个new String("XYZ"),构造函数需要创建一个对象

最后两个字符串相加会再StringPool中再创建一个对象

因此总共创建了4个对象

String的Equals()和==比较的更多相关文章

  1. 关于String的equals问题和StringBuilder问题

    今天弄了一下String和StringBuilder,遇到了一些问题. 老规矩上代码图片: 发现stringBuilder的equals方法有问题,看了一下源码,发现stringbuilder没有重写 ...

  2. Java String 的equals, == , hascode的区别

    1.equals 和 == ==在java中是比较引用的,即在内存中的地址.而String的equals()是比较字符串的内容 http://blog.csdn.net/barryhappy/arti ...

  3. String的equals()方法源码解析

    每个String对象在创建的时候都构造了一个char类型的final声明的不可替换数组,数组中的每一个元素即字符串对应的每一个字符如图: String的equals()在比较的时候会进行两步比较: 1 ...

  4. java:String使用equals和==比较的区别

    原文链接:http://www.cnblogs.com/tinyphp/p/3768214.html "=="操作符的作用 1.用于基本数据类型的比较 2.判断引用是否指向堆内存的 ...

  5. Java中String 的equals 和==详解

    一.Java中数据存储区域包括: 1.寄存器:最快的存储区,由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new ...

  6. String使用equals方法和==分别比较的是什么?

    equals方法和==的区别   首先大家知道,String既可以作为一个对象来使用,又可以作为一个基本类型来使用.这里指的作为一个基本类型来使用只是指使用方法上的,比如String s = &quo ...

  7. java String的equals,intern方法(转载)

    JAVA中的equals和==的区别 ==比较的是2个对象的地址,而equals比较的是2个对象的内容. 显然,当equals为true时,==不一定为true: 基础知识的重要性,希望引起大家的重视 ...

  8. 【Java】整理关于java的String类,equals函数和比较操作符的区别

    初学 Java 有段时间了,感觉似乎开始入了门,有了点儿感觉但是发现很多困惑和疑问而且均来自于最基础的知识折腾了一阵子又查了查书,终于对 String 这个特殊的对象有了点感悟大家先来看看一段奇怪的程 ...

  9. 【Java】Java里String 的equals和==

    Java里面有对象和对象的引用的概念,在String方面,==比较的是引用,equals比较的是对象的具体值. String s1 = new String("abc");Stri ...

  10. String的equals方法和==

    String类的对象是字符串常量,一切看起来改变了String对象的操作,其实只是改变了字符串引用变量所引用的字符串罢了. Java中的字符串存放在一个公共的存储池中,引用指向存储池中相应的位置,编译 ...

随机推荐

  1. 大二下学期开学java测试

    我们在2月13日下午进行了java测试(是一个新闻类型的题),通过这一个测试我进行了以下总结: 我对于javaweb的框架构建和加密密码,还有一些不同人物功能的实现,使得我在这次得考试中成绩不太理想. ...

  2. fiddler抓包返回304

    为了验证部分场景需要对接口返回数据进行修改后验证前端代码逻辑处理,发现同一域名下其他接口都正常返回,但是某个端口返回304. 操作步骤是页面打开后接口已经请求了,这时候才打开fiddler抓取请求拦截 ...

  3. 扫二维码 下载app

    <?phpheader("Access-Control-Allow-Origin: https:// ");$version = PAPI_GetSafeParam('ver ...

  4. 【ADB命令】安装app

    在电脑上安装以下指令 adb install app的文件位置

  5. python 发送 application/x-www-form-urlencoded 类型的数据包

    在网上百度了很多,坑的要死,基本不咋好用,自己多尝试了几遍,成功实现了. data 的构建方式 data = f"page={page}&sign={sign}&t={t}& ...

  6. 各种相机以及图片-SLAM14CP5

    --2020.10.20 开始学习SLAM.想着从SLAM开始然后做三维重建.前面的李群李代数以及旋转四元数有点复杂.都看过了一遍.但不太理解就先放放.希望接下去能够顺利进行.数学基础可能不是很好,公 ...

  7. 【python】绘图坐标轴标题中包含上标或下标

    plt.ylabel("流量($\mathregular{m^3}$/s)")          #绘图坐标轴添加上标$\mathregular{m^3}$,若是下标m_3 不加m ...

  8. scala中的数据类型

    一.Scala的数据类型 (1). scala中一切数据都是对象,都是Any的子类: (2).scala中数据类型分为两大类:数值类型(AnyVal,即any value,任意值).引用类型(AnyR ...

  9. 20200922--计算矩阵边缘元素之和(奥赛一本通P91 3二维数组)

    输入一个整数矩阵,计算位于矩阵边缘的元素之和.所谓矩阵边缘的元素,就是就一行和最后一行以及第一列和最后一列的元素. 输入; 第一行分别为矩阵的行数m和列数n(m<100,n<100),两者 ...

  10. white album句子

    1.不论是真心的笑,还是真心的生气,我都做不到.我只是个胆小的骗子.