重拾Java--功底篇之String
2017-10-18 22:16
204 查看
今天看书看到这样一段代码,感觉十分有趣,在这放一下
呐尼,这边怎么用了”==”,不是应该用equals()么?
那么其实,这段代码运行的最终结果是true,如果你了解原理,这篇文章完全可以跳过,如果是猜的小伙伴,有兴趣可以继续往下看一看
想了解为什么会是true,需要了解以下几个知识点:
1.“==”是做什么的?
2.equals()呢?
3.a和b在内存中是什么样存在的?
4.编译时的优化方案
但如果是引用类型的对象,那么比较的其实是两个对象的地址。
来看下equals()在Object类中的实现:
原来源码的原始实现用的就是==比较两个对象的地址是否一致,so easy。那么再来看下String类中的equals方法是怎么样的呢?
大致看一下代码,分为如下几个步骤:
1. 先判断两个对象地址是否相同,如果地址相同,则返回true
2. 再判断传入对象是否为String,若不是则返回false
3. 判断传入的String长度与当前String是否一致,若不一致则返回false
4. 循坏匹配两个String的每个字符是否相等,若不相等,返回false
5. 直到所有字符比较完成,返回true
好了,现在理解了String类中的equals如何工作了
Ps:在JDK1.7中,如果Hash相关的集合的key是String类型,不再使用hashCode,而是用一种hash32属性。
当然编译器做的优化远远不止这些,这边只是稍微提及一下。
关于StringBuilder类的append源码在这就不分析了。(源码什么的 还是很有趣的!)
这边提一个
大致意思就是,返回一个与当前字符串内容相同,且在Perm Gen(永久代,即内存的永久保存区域)中保证全局唯一的字符串。
wtf,这是什么意思呢?
首先,Perm Gen是常量池中的一块,它对于同一个值的字符串保证全局唯一。如果一个字符串调用intern(),JVM首先会去常量池中通过equals()选择等值的String,若存在,返回常量池中这个String的地址,如果未找到,会创建等值的字符串,再返回新创建空间的地址。
到这里,有点小累,来个例题放松放松吧
答案是:
private static void test(){ String a = "a" + "b"; String b = "ab"; System.out.println(a == b); }
呐尼,这边怎么用了”==”,不是应该用equals()么?
那么其实,这段代码运行的最终结果是true,如果你了解原理,这篇文章完全可以跳过,如果是猜的小伙伴,有兴趣可以继续往下看一看
想了解为什么会是true,需要了解以下几个知识点:
1.“==”是做什么的?
2.equals()呢?
3.a和b在内存中是什么样存在的?
4.编译时的优化方案
==
首先,”==”在Java中,原始类型如byte、short、int、long、float、double、boolean、char都是直接比较它们的值是否相等,这个不用多说。但如果是引用类型的对象,那么比较的其实是两个对象的地址。
equals()
equals()方法在jdk源码的Object类中被定义,它可以被重写。来看下equals()在Object类中的实现:
public boolean equals(Object obj) { return (this == obj); }
原来源码的原始实现用的就是==比较两个对象的地址是否一致,so easy。那么再来看下String类中的equals方法是怎么样的呢?
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; }
大致看一下代码,分为如下几个步骤:
1. 先判断两个对象地址是否相同,如果地址相同,则返回true
2. 再判断传入对象是否为String,若不是则返回false
3. 判断传入的String长度与当前String是否一致,若不一致则返回false
4. 循坏匹配两个String的每个字符是否相等,若不相等,返回false
5. 直到所有字符比较完成,返回true
好了,现在理解了String类中的equals如何工作了
hashCode()
讲到equals()不得不提一下hashCode(),这是一个Object类提供的native(本地)方法,作用是获取对象的hashCode,它的返回值与System.identityHashCode(Obj)一致。是一组由对象头部一部分二进制位组成的数字,用于标识该对象,但绝不等价于地址。这个hashCode主要在HashMap、HashSet等集合类中的对象写入和查找等算法中用于算法快速定位数据之用。Ps:在JDK1.7中,如果Hash相关的集合的key是String类型,不再使用hashCode,而是用一种hash32属性。
编译时优化
JVM有时会在编译时对代码进行自动优化,如针对代码String a = "a" + "b",因为”a”和”b”都是常量,他们都储存在常量池中,在编译时其实已经转化成了
String a = "ab",无须运行时再计算,同样的道理还有
int i = 1 + 3,编译时自动优化为
int i = 4。
当然编译器做的优化远远不止这些,这边只是稍微提及一下。
String的”+”操作
这边稍微瞄一眼String的”+”操作的工作原理,例如代码String b = a + "b",其中a是一个String类型的字符串,因为a是一个变量,因此这段代码编译好之后是这个样子滴:
StringBuilder temp = new StringBuilder(); temp.append(a).append("b"); String b = temp.toString();
关于StringBuilder类的append源码在这就不分析了。(源码什么的 还是很有趣的!)
这边提一个
intern()方法,这个方法的源码注释是这个样子的
* @return a string that has the same contents as this string, but is * guaranteed to be from a pool of unique strings.
大致意思就是,返回一个与当前字符串内容相同,且在Perm Gen(永久代,即内存的永久保存区域)中保证全局唯一的字符串。
wtf,这是什么意思呢?
首先,Perm Gen是常量池中的一块,它对于同一个值的字符串保证全局唯一。如果一个字符串调用intern(),JVM首先会去常量池中通过equals()选择等值的String,若存在,返回常量池中这个String的地址,如果未找到,会创建等值的字符串,再返回新创建空间的地址。
到这里,有点小累,来个例题放松放松吧
public class test { public static String getA(){return "a";} public static void main(String[] args) { String a = "a"; final String _a = "a"; String b = a + "b"; String c = _a + "b"; String d = getA() + "b"; String e = new String(b); String compare = "ab"; System.out.println(b == compare); System.out.println(c == compare); System.out.println(d == compare); System.out.println(e == compare); System.out.println(d.intern() == compare); System.out.println(e.intern() == compare); System.out.println(e.intern() == d.intern()); } }
答案是:
false true false false true true true
相关文章推荐
- java功底之String的比较问题
- Java String与StringBuffer
- 在java1.7之前 switch中使用String作为分支条件
- Java.lang.String提供的常用的方法
- 黑马程序员-Java基础-String和StringBuffer学习笔记
- String 类(java)
- 【java基础学习一】int[]、Integer[]、String[] 排序( 正序、倒叙)、去重
- java 基于JDK中的源码总结下String二
- Java基本的API中,String,StringBuffer,Math,Wapper class的基本应用
- Java String和new String,Stringbuilder,StringBuffer
- java String s = null; & String s="";
- java.lang.NumberFormatException: For input string:
- Java中String与StringBuffered常见笔试题
- 关于 Java中switch条件是否能为string类型
- 转:java中 String和StringBuffer的区别
- Java功底之static、final、this、super
- Java从入门到精通 - JavaString 字符串拼接,截取,查找及日期转换
- 测验下你的java功底 经验与细节
- Java基础 String StringBuffer StringBuilder
- Java中string的特性