在开发过程当中String是一个高频使用的类,可是一直没有仔细去阅读过源码。打开源码得知String是一个final的类,它实现了Serializable、Comparable和CharSequence接口java
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 //省略... }
String类包含三个属性:数组
/** 存储字符串中的字符*/ private final char value[]; /** 缓存string的hashcode值 */ private int hash; // Default to 0 /** * 序列持久化 */ private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
String的底层使用char数组实现的。String重写了Object的equals和hashcode的方法。缓存
String的equals方法实现以下:jvm
/** * 比较当前字符串和指定的对象,只有当指定对象不为null而且对象中的字符序列相同时 * 才返回true */ public boolean equals(Object anObject) { //两个对象的引用地址相同返回true if (this == anObject) { return true; } //只有String类型的数据才有效 if (anObject instanceof String) { String anotherString = (String) anObject; int n = value.length; //若是包含的字符长度不相等返回false if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; //从后往前判断单个字符,同等序号若是不相等则返回false while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
String的hashCode实现以下:测试
String是使用value值来做为hash运算,那么若是String的value相等那么它们的hashCode值一定相等,那么用String的equals比较也是相等的,同时也能够看出对于String若是它的equals相等,那么它的hashCode值优化
也必定相等,固然hashCode值相等不能表明两个String相等。this
在String的Hash计算中使用一个计算常数31,31是通过测试均匀分布的获得的结果,并且31能够被jvm优化采用移位运算31 = (i<<5)-1code
/** * 返回字符串的hash值 * 计算公式: * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] * s[i]是指String中的字符,n是指String的长度 */ public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }
String intern方法介绍:intern方法是一个native的方法,当intern方法被调用,它会使用equals方法去字符串常量池中比较查找,若是找到则返回,若是没有找到的将新的字符串添加到字符串常量池中,而后返回对象的引用。对于任何的两个String对象s和t,当前仅当s.equals(t)为true时,s.intern()==t.intern()才为true对象
public native String intern();
String的内存操做:接口
在jvm内存分配中有两个重要的部分,一个是heap一个是stack,栈用于存储对象的引用,
heap用户存储具体的对象。在jdk1.7后(字符串常量池被移到了heap中)jvm分配 一些内存专门用于存储string的字面量,这是堆内存的一部分,它被称做字符串常量池(String Constant Pool),例如 :String a = "abc"; 若是使用了new操做来建立字符串则对象会被存储到堆内存中
注意:当你使用一个字面量来建立一个String对象时,jvm会首先在字符串常量池中检查是否已经存在,若是找到则返回对象的引用,若是没有的建立一个新的对象