JDK1.8源码——java.lang.String 类
Posted 小辣椒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK1.8源码——java.lang.String 类相关的知识,希望对你有一定的参考价值。
String 类也是java.lang 包下的一个类,算是日常编码中最常用的一个类了,那么本篇博客就来详细的介绍 String 类。
1、String 类的定义
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {}
和上一篇博客所讲的 Integer 类一样,这也是一个用 final 声明的常量类,不能被任何类所继承,而且一旦一个String对象被创建, 包含在这个对象中的字符序列是不可改变的, 包括该类后续的所有方法都是不能修改该对象的,直至该对象被销毁,这是我们需要特别注意的(该类的一些方法看似改变了字符串,其实内部都是创建一个新的字符串,下面讲解方法时会介绍)。接着实现了 Serializable接口,这是一个序列化标志接口,还实现了 Comparable 接口,用于比较两个字符串的大小(按顺序比较单个字符的ASCII码),后面会有具体方法实现;最后实现了 CharSequence 接口,表示是一个有序字符的集合,相应的方法后面也会介绍。
2、字段属性
/** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L;
一个 String 字符串实际上是一个 char 数组。
3、构造方法
String 类的构造方法很多。可以通过初始化一个字符串,或者字符数组,或者字节数组等等来创建一个 String 对象。
String str1 = "abc";//注意这种字面量声明的区别,文末会详细介绍 String str2 = new String("abc"); String str3 = new String(new char[]{\'a\',\'b\',\'c\'})
4、equals(Object anObject) 方法
instanceof 运算符 用于:判断 该运算符前面引用类型变量指向的对象是否是后面类,或者其子类、接口实现类创建的对象。如果是则返回true,否则返回false, 其使用格式如下: 引用类型变量 instanceof (类、抽象类或接口)
1 /** 2 * Compares this string to the specified object. The result is {@code 3 * true} if and only if the argument is not {@code null} and is a {@code 4 * String} object that represents the same sequence of characters as this 5 * object. 6 * 7 * @param anObject 8 * The object to compare this {@code String} against 9 * 10 * @return {@code true} if the given object represents a {@code String} 11 * equivalent to this string, {@code false} otherwise 12 * 13 * @see #compareTo(String) 14 * @see #equalsIgnoreCase(String) 15 */ 16 public boolean equals(Object anObject) { 17 if (this == anObject) { 18 return true; 19 } 20 if (anObject instanceof String) { 21 String anotherString = (String)anObject; 22 int n = value.length; 23 if (n == anotherString.value.length) { 24 char v1[] = value; 25 char v2[] = anotherString.value; 26 int i = 0; 27 //比较每一个字符的值 28 while (n-- != 0) { 29 if (v1[i] != v2[i]) 30 return false; 31 i++; 32 } 33 return true; 34 } 35 } 36 return false; 37 }
String 类重写了 equals 方法,比较的是组成字符串的每一个字符是否相同,如果都相同则返回true,否则返回false。
5、hashCode() 方法
1 /** 2 * Compares this string to the specified object. The result is {@code 3 * true} if and only if the argument is not {@code null} and is a {@code 4 * String} object that represents the same sequence of characters as this 5 * object. 6 * 7 * @param anObject 8 * The object to compare this {@code String} against 9 * 10 * @return {@code true} if the given object represents a {@code String} 11 * equivalent to this string, {@code false} otherwise 12 * 13 * @see #compareTo(String) 14 * @see #equalsIgnoreCase(String) 15 */ 16 public boolean equals(Object anObject) { 17 if (this == anObject) { 18 return true; 19 } 20 if (anObject instanceof String) { 21 String anotherString = (String)anObject; 22 int n = value.length; 23 if (n == anotherString.value.length) { 24 char v1[] = value; 25 char v2[] = anotherString.value; 26 int i = 0; 27 while (n-- != 0) { 28 if (v1[i] != v2[i]) 29 return false; 30 i++; 31 } 32 return true; 33 } 34 } 35 return false; 36 }
String 类的 hashCode 算法很简单,主要就是中间的 for 循环,计算公式如下:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
s 数组即源码中的 val 数组,也就是构成字符串的字符数组。这里有个数字 31 ,为什么选择31作为乘积因子,而且没有用一个常量来声明?主要原因有两个:
①、31是一个不大不小的质数,是作为 hashCode 乘子的优选质数之一。
②、31可以被 JVM 优化,31 * i = (i << 5) - i。因为移位运算比乘法运行更快更省性能。
具体解释可以参考这篇文章。https://www.cnblogs.com/nullllun/p/8350178.html
6.split(String regex) 和 split(String regex, int limit) 方法
split(String regex) 将该字符串拆分为给定正则表达式的匹配。split(String regex , int limit) 也是一样,不过对于 limit 的取值有三种情况:
①、limit > 0 ,则pattern(模式)应用n - 1 次
1 String str = "a,b,c"; 2 String[] c1 = str.split(",", 2); 3 System.out.println(c1.length);//2 4 System.out.println(Arrays.toString(c1));//{"a","b,c"}
②、limit = 0 ,则pattern(模式)应用无限次并且省略末尾的空字串
1 String str2 = "a,b,c,,"; 2 String[] c2 = str2.split(",", 0); 3 System.out.println(c2.length);//3 4 System.out.println(Arrays.toString(c2));//{"a","b","c"}
③、limit < 0 ,则pattern(模式)应用无限次
1 String str2 = "a,b,c,,"; 2 String[] c2 = str2.split(",", -1); 3 System.out.println(c2.length);//5 4 System.out.println(Arrays.toString(c2));//{"a","b","c","",""}
下面我们看看底层的源码实现。对于 split(String regex) 没什么好说的,内部调用 split(regex, 0) 方法:
1 public String[] split(String regex) { 2 return split(regex, 0); 3 }
重点看 split(String regex, int limit) 的方法实现:
1 public String[] split(String regex, int limit) { 2 /* 1、单个字符,且不是".$|()[{^?*+\\\\"其中一个 3 * 2、两个字符,第一个是"\\",第二个大小写字母或者数字 4 */ 5 char ch = 0; 6 if (((regex.value.length == 1 && 7 ".$|()[{^?*+\\\\".indexOf(ch = regex.charAt(0)) == -1) || 8 (regex.length() == 2 && 9 regex.charAt(0) == \'\\\\\' && 10 (((ch = regex.charAt(1))-\'0\')|(\'9\'-ch)) < 0 && 11 ((ch-\'a\')|(\'z\'-ch)) < 0 && 12 ((ch-\'A\')|(\'Z\'-ch)) < 0)) && 13 (ch < Character.MIN_HIGH_SURROGATE || 14 ch > Character.MAX_LOW_SURROGATE)) 15 { 16 int off = 0; 17 int next = 0; 18 boolean limited = limit > 0;//大于0,limited==true,反之limited==false 19 ArrayList<String> list = new ArrayList<>(); 20 while ((next = indexOf(ch, off)) != -1) { 21 //当参数limit<=0 或者 集合list的长度小于 limit-1 22 if (!limited || list.size() < limit - 1) { 23 list.add(substring(off, next)); 24 off = next + 1; 25 } else {//判断最后一个list.size() == limit - 1 26 list.add(substring(off, value.length)); 27 off = value.length; 28 break; 29 } 30 } 31 //如果没有一个能匹配的,返回一个新的字符串,内容和原来的一样 32 if (off == 0) 33 return new String[]{this}; 34 35 // 当 limit<=0 时,limited==false,或者集合的长度 小于 limit是,截取添加剩下的字符串 36 if (!limited || list.size() < limit) 37 list.add(substring(off, value.length)); 38 39 // 当 limit == 0 时,如果末尾添加的元素为空(长度为0),则集合长度不断减1,直到末尾不为空 40 int resultSize = list.size(); 41 if (limit == 0) { 42 while (resultSize > 0 && list.get(resultSize - 1).length() == 0) { 43 resultSize--; 44 } 45 } 46 String[] result = new String[resultSize]; 47 return list.subList(0, resultSize).toArray(result); 48 } 49 return Pattern.compile(regex).split(this, limit); 50 }
以上是关于JDK1.8源码——java.lang.String 类的主要内容,如果未能解决你的问题,请参考以下文章
org.json.JSONException: Value okhttp3.internal.http.RealResponseBody@da68fa1 of type java.lang.Strin