String是我们使用最频繁的一个类,在我们的日常开发中String对象的比较也是最为常见的。当然也是面试和笔试经常会被问到的的一个知识点。今天我们就来总结一下String对象的比较以及常被考的几个函数如:intern(), valueOf(), equals()

一:String的介绍

String是一个被定义为final的class。所以从定义上就可以看出String是一个引用类型而不是基本类型,第2个就是它既然是一个final类那就不能被继承。String是一个不可变的字符串,也就说如果涉及到2个字符串相加的操作,就会返回一个临时的字符串对象(相加的结果)。

二:”==”的比较

“==”在基本数据类型中属于关系运算符,比较的是2个基本数据类型值是否相等,在引用数据类型中比较的是2个对象的地址是否相等。例如下面的例子中,第一个比较输出的是true,而第2个则输出false

int num1 = 10;

int num2 = 10;

int num3 = 20;

System.out.println(num1 == num2); //true

System.out.println(num2 == num3); //false

下面我们来看一下,在String中 “==”的比较结果

String str1 = "string";

String str2 = "string";

String str3 = new String("string");

String str4 = new String("string");

System.out.println(str1 == str2); //true

System.out.println(str2 == str3); //false

System.out.println(str3 == str4); //false

从上面的例子中我们发现,比较结果是true, false, false,下面我们来分析一下这个结果的原因:

String str1 = "string";执行这条语句时,会先去常量池中查找是否有"string"这个字符串,若没有,则将string这个串放入到常量池中,然后指向常量池中的"string"。 如果有则在栈中创建一个str1,然后指向常量池中的"string";

String str2 = "string";执行这条语句时,也会先去常量池中是否有"string"这个字符串,发现有这个字符,然后在栈中创建一个str2,然后指向常量池中的"string"。所以str1和str2的比较结果是true.

String str3 = new String("string");执 行这条语句时,会先在堆中创建一个"string"串(不去care常量池中是否有"string"这个串),然后再在栈中中创建一个str3,并指向堆中的"string"对象,因此str3则是指向了堆中”string”的地址。所以str2,str3的返回结果是False.

String str4 = new String("string");执行这条语句时,会先在堆中创建一个"string"串,然后再在栈中中创建一个str4,并指向堆中刚创建的新的"string"对象地址,所以str4,str3的返回结果也是False.

三:equals的比较

equals是Object中的方法,所以在基础数据类型中是不能用equals来比较的。equals在Object中的实现只是比较的2个引用是否相等 (2个对象指的是否是同一个对象)。 方法的实现是: return this == x; 但是String是重写了equals方法的,在String类中,equals是比较的2个字符串每一个字符是否相等。所以下面的输出结果都是true:

System.out.println(str1.equals(str2)); //true

System.out.println(str2.equals(str3)); //true

System.out.println(str3.equals(str4)); //true

四:String.intern()

intern方法是先去查常量池中是否存在该字符串,如果存在则返回常量池中该字符串的引用。当string对象调用intern方法后,程序会先去常量池中查找该字符串,如果没有,则现在常量池中创建一个副本用来保存这个字符串在堆中的的地址,如果存在该字符串,则返回常量池中改副本的地址。(jdk1.8),下面来看一个例子:

String a1 = new String("aa");

String a2 = "aa";

System.out.println(a1 == a2); //false

很明显,a1指向的是堆中字符串的地址,而a2指向的是常量池中的字符串的地址,所以a1,a2比较的结果是false.下面让我们来试一下intern方法的微妙

String a3 = new String("cxy");

a3.intern();

String a4 = "cxy";

String a9 = new String("cxy").intern();

System.out.println(a3 == a3.intern()); //false

System.out.println(a4 == a4.intern()); //true

System.out.println(a9 == a9.intern()); //true

System.out.println(a3 == a9); //false

System.out.println(a4 == a9); //true

System.out.println(a3 == a4); //false

String a3 = new String("cxy");在执行这行代码的时候,首先会在堆上创建”cxy”对象,然后在常量池中创建一个副本用来保存”cxy”在堆中的地址.(但此时a3依然指向的是堆中”cxy”的地址,而a3.intern()指向的是常量池中的地址。所以a3== a3.intern();返回false)

String a4 = "cxy";在执行这行代码时,a4发现常量池中有"cxy",则将常量池中的"cxy"地址赋给了a4 (所以a4 == a4.intern()返回true,)

String a9 = new String("cxy").intern();在执行这段代码时,首先在堆上创建"cxy",发现常量池中有"cxy"则不创建,但是我们的代码用调用了.intern(),所以程序又将常量池中的"cxy"地址赋给了a9 (所以a9 == a9.intern()返回true,a4和a9的比较也是true)

因为a3指向的是堆中"Cxy"的地址,而a4,a9都是指向常量池中"cxy"的地址,所以a3与a4的比较是false,与a9的比较也是false

String a5 = new String("abc").intern();

String a6 = "abc";

System.out.println(a5 == a5.intern());//true

System.out.println(a5 == a6);//true

通过前面几个case的分析,所以上面的案例, 返回true我们就很清楚了。(首先在堆上创建"abc",然后再在常量池中创建"abc"的引用,再把常量池中的地址赋值给a5,而a6则直接从常量池中获取引用,所以,a5,a6,a5.intern()的比较都是true)

String a7 = new String("abc") + new String("d");

a7.intern();

String a8 = "abcd";

System.out.println(a7 == a7.intern());// true

System.out.println(a7 == a8); //true

但是对于new String+ new String这中操作,返回的比较结果是true,(个人猜测:应该是jvm对于new String + new string 做了优化,使得a7直接指向了常量池)

五:String.valueOf()

这是标准的类型转换,将object转成String类型的值。使用这种方法时,需要注意的是类型必须能转成String类型。valueOf内部实现是: return obj.toString();toString()的内部实现是: return this;

String str = new String("test");

String str5 = String.valueOf("test");

String str6 = String.valueOf("test");

System.out.println(str == str5); //false

System.out.println(str == str6); //false

System.out.println(str5 == str6); //true

所以str是存在栈里面, 指向堆中"test"对象的地址,str5,str6,都是指向的是"test"对象的地址(因为返回的都是”test”对象的this指针,所以str == str5 =>false;str == str6 => false;str5 == str6=> true)

String str7 = String.valueOf(str);

String str8 = String.valueOf(str);

System.out.println(str == str7); //true

System.out.println(str == str8); //true

System.out.println(str7 == str8); //true

str7, str8,都是指向str对象的地址 (因为toString()返回的都是str的this指针,所以str, str7, str8的比较结果都是true.)

java string == 比较,Java 基础 之 String 的比较相关推荐

  1. Java修炼之路——基础篇——String

    String 1:字符串的不可变性 什么是不可变对象?不可变对象是指创建后无法变更的对象 String为什么是不可变的?String类为final,并且内部字符数组也为final.所以String对象 ...

  2. java引入string类_Java基础教程——String类

    String类 Java程序中的所有字符串字面值(如 "abc" )都是String的实例 字符串是常量(因为 String 对象是不可变的,所以可以共享) 字符串的本质是字符数组 ...

  3. java string类方法_Java基础学习——String类及其方法

    String类概述 该类被final修饰,无子类,不可被复写.创建的对象一旦初始化,其内容不可被改变. String类复写了Object类中的equals()定义了自己的独特内容,该方法用于判断字符串 ...

  4. Java基础:String类

    相关阅读 Java基础:String类 Java字符串格式化 Java基础:正则表达式 1. 概述 字符串是由多个字符组成的一串数据(字符序列),字符串可以看成是字符数组. 在实际开发中,字符串的操作 ...

  5. java的知识点15——String基础、String类和常量池、String类常用的方法、字符串相等的判断、组合模式

    String基础 1. String类又称作不可变字符序列. 2. String位于java.lang包中,Java程序默认导入java.lang包下的所有类. 3. Java字符串就是Unicode ...

  6. abstract类_012 JAVA 抽象类、接口、String类的基础了解

    1.抽象方法和抽象类 抽象方法:使用abstract修饰的方法,没有方法体,只有声明.抽象方法可以当做是一种规范,让子类必须实现. 注意: 1.抽象方法没有方法体,只能以分号结尾 2.抽象方法只能声明 ...

  7. Java基础之String,StringBuilder,StringBuffer三者的区别

    Java基础之String,StringBuilder,StringBuffer三者的区别 目录 运行速度方面 线程安全方面 小结 1. 运行速度方面 运行速度,在这方面运行速度快慢为:StringB ...

  8. Java基础之String深入解析

    Java基础之String深入解析 以下是本文目录大纲 生成地方和地址指向,intern()方法 String可否被继承? 1. 生成地方和地址指向,intern()方法 先看代码 String s1 ...

  9. bytes数组转string指定编码_好程序员Java学习路线分享Java基础之string

    好程序员Java学习路线分享Java基础之string 好程序员Java培训 先来讲一下字符串 字串符分类: 不可变字符串:----String.字符串本身不能发生改变,与指向字符串的引用无关. St ...

  10. java string hash变量_java基础(六)-----String性质深入解析

    本文将讲解String的几个性质. 一.String的不可变性 对于初学者来说,很容易误认为String对象是可以改变的,特别是+链接时,对象似乎真的改变了.然而,String对象一经创建就不可以修改 ...

最新文章

  1. JavaScript异步史
  2. [树组BIT]训练两题重新理解ver.
  3. NYOJ 685 查找字符串 字典树
  4. Linux常用服务部署与优化之NFS篇
  5. Anaconda3自带jupyter
  6. 电脑任务管理器快捷键_电脑知识小常识
  7. java图片格式转化(例如jpg格式转化png)
  8. 谈谈iOS获取调用链
  9. The user specified as a definer (#39;root#39;@#39;%#39;) does not exist
  10. LEAGUE TABLES【模拟】
  11. STM32F10x随笔(gcc+scons)
  12. 【COGS2652】—天文密葬法(分数规划+长链剖分)
  13. js中的instanceof运算符
  14. 关于Jedis和lettuce以及springDataRedis的一些区别
  15. hdu 5823 color II 状压dp
  16. Visual Studio 2013 编译Notepad++源码
  17. 深入浅出SCSI子系统(五)SCSI设备探测
  18. 运放搭建电压电流转换电路分析
  19. wps里的茶色字体怎么设置_wps字体加茶色背景2 wps茶色如何设置
  20. swfkit打包swf文件步骤(图文教程)

热门文章

  1. 【英语学习】【WOTD】gormless 释义/词源/示例
  2. 求矩阵全部特征值和特征向量的QR方法
  3. 混合app用百分比还是rem_[笔记]em, rem最佳实践
  4. 扫地机器人水箱背景_你真的懂扫地机器人吗?这些不为人知的小细节值得一看...
  5. ios设计规范_e微课5期:ios设计规范带来的设计细节(下篇)
  6. 矩形法_教程 | 三个案例教会你大师都爱用的矩形造字法!
  7. python中for循环缩进_Python基础- 缩进,选择和循环
  8. 从GPU到3D渲染:游戏图形渲染技巧与性能优化
  9. 【音频处理】如何“认识”一个滤波器?
  10. 关于Go语言,你可能会讨厌的五件事