本章源码分析基于JDK1.7
实现的接口
String类被final修饰词修饰,代表不可修改的特性,它实现了三个接口,Serializable是序列化接口,Compareble是排序接口,Char是字符序列接口。

public final class String implements Serializable, Comparable, CharSequence
主要成员变量
char[]:String通过char[]来实现String的各种功能,字符串由字符数组实现。

hash:用于缓存hash值,因为String类是final不可修改的,所以hash值也是固定的,为了避免重复计算hash值而缓存。

CASE_INSENSITIVE_ORDER:排序器,由上可知String类实现了Compareble接口,这里的Comparator用于忽视大小写的字符串的比较。

private final char[] value;
private int hash;
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator();

构造函数
String共有15个重载构造函数,入参这几种:空、char[]、String、StringBuffer、StringBuilder、byte[],通过这些来构造字符串对象。

//第一种,入参为空,新建了大小为0的char数组,这就是空字符串
public String() {this.hash32 = 0;this.value = new char[0];
}//第二种,入参为String对象,直接将入参的属性复制过来
public String(String var1) {this.hash32 = 0;this.value = var1.value;this.hash = var1.hash;
}//第三种,入参为char[],将value赋值为入参var1
public String(char[] var1) {this.hash32 = 0;this.value = Arrays.copyOf(var1, var1.length);
}//第四种,入参为char[],截取char[]中从var2到var3的字符作为字符串
public String(char[] var1, int var2, int var3) {this.hash32 = 0;if (var2 < 0) {throw new StringIndexOutOfBoundsException(var2);} else if (var3 < 0) {throw new StringIndexOutOfBoundsException(var3);} else if (var2 > var1.length - var3) {throw new StringIndexOutOfBoundsException(var2 + var3);} else {this.value = Arrays.copyOfRange(var1, var2, var2 + var3);}
}public String(int[] var1, int var2, int var3) {this.hash32 = 0;if (var2 < 0) {throw new StringIndexOutOfBoundsException(var2);} else if (var3 < 0) {throw new StringIndexOutOfBoundsException(var3);} else if (var2 > var1.length - var3) {throw new StringIndexOutOfBoundsException(var2 + var3);} else {int var4 = var2 + var3;int var5 = var3;int var7;for(int var6 = var2; var6 < var4; ++var6) {var7 = var1[var6];if (!Character.isBmpCodePoint(var7)) {if (!Character.isValidCodePoint(var7)) {throw new IllegalArgumentException(Integer.toString(var7));}++var5;}}char[] var10 = new char[var5];var7 = var2;for(int var8 = 0; var7 < var4; ++var8) {int var9 = var1[var7];if (Character.isBmpCodePoint(var9)) {var10[var8] = (char)var9;} else {Character.toSurrogates(var9, var10, var8++);}++var7;}this.value = var10;}
}/** @deprecated */
@Deprecated
public String(byte[] var1, int var2, int var3, int var4) {this.hash32 = 0;checkBounds(var1, var3, var4);char[] var5 = new char[var4];int var6;if (var2 == 0) {for(var6 = var4; var6-- > 0; var5[var6] = (char)(var1[var6 + var3] & 255)) {;}} else {var2 <<= 8;for(var6 = var4; var6-- > 0; var5[var6] = (char)(var2 | var1[var6 + var3] & 255)) {;}}this.value = var5;
}/** @deprecated */
@Deprecated
public String(byte[] var1, int var2) {this(var1, var2, 0, var1.length);
}private static void checkBounds(byte[] var0, int var1, int var2) {if (var2 < 0) {throw new StringIndexOutOfBoundsException(var2);} else if (var1 < 0) {throw new StringIndexOutOfBoundsException(var1);} else if (var1 > var0.length - var2) {throw new StringIndexOutOfBoundsException(var1 + var2);}
}public String(byte[] var1, int var2, int var3, String var4) throws UnsupportedEncodingException {this.hash32 = 0;if (var4 == null) {throw new NullPointerException("charsetName");} else {checkBounds(var1, var2, var3);this.value = StringCoding.decode(var4, var1, var2, var3);}
}public String(byte[] var1, int var2, int var3, Charset var4) {this.hash32 = 0;if (var4 == null) {throw new NullPointerException("charset");} else {checkBounds(var1, var2, var3);this.value = StringCoding.decode(var4, var1, var2, var3);}
}public String(byte[] var1, String var2) throws UnsupportedEncodingException {this(var1, 0, var1.length, (String)var2);
}public String(byte[] var1, Charset var2) {this(var1, 0, var1.length, (Charset)var2);
}public String(byte[] var1, int var2, int var3) {this.hash32 = 0;checkBounds(var1, var2, var3);this.value = StringCoding.decode(var1, var2, var3);
}public String(byte[] var1) {this((byte[])var1, 0, var1.length);
}public String(StringBuffer var1) {this.hash32 = 0;synchronized(var1) {this.value = Arrays.copyOf(var1.getValue(), var1.length());}
}public String(StringBuilder var1) {this.hash32 = 0;this.value = Arrays.copyOf(var1.getValue(), var1.length());
}String(char[] var1, boolean var2) {this.hash32 = 0;this.value = var1;
}/** @deprecated */
@Deprecated
String(int var1, int var2, char[] var3) {this(var3, var1, var2);
}

length方法
通过获取char[]的长度来获取字符串的长度

public int length() {return this.value.length;
}

isEmpty方法
通过判断char[]的长度是否为0来判断是否为空

public boolean isEmpty() {return this.value.length == 0;
}

charAt方法
通过char[]数组下标获取到对应位置的char字符

public char charAt(int var1) {if (var1 >= 0 && var1 < this.value.length) {return this.value[var1];} else {throw new StringIndexOutOfBoundsException(var1);}
}

equals方法
首先比较内存地址,再判断是否是String类型,然后再判断长度,最后逐个比较其中的char。

public boolean equals(Object var1) {//首先比较内存地址if (this == var1) {return true;} else {//判断var1是否是String类型if (var1 instanceof String) {//如果是则强转String var2 = (String)var1;//获取当前String中char[]的长度int var3 = this.value.length;//如果传入的var1和当前String中char[]的长度一样if (var3 == var2.value.length) {char[] var4 = this.value;char[] var5 = var2.value;//将传入的var1和当前字符串中char[]中字符逐个比较,若有一个不一致则返回falsefor(int var6 = 0; var3-- != 0; ++var6) {if (var4[var6] != var5[var6]) {return false;}}return true;}}return false;}
}

hashCode方法
这里的hash值计算有个特点,就是String内部缓存了hash值,如果hash值不为0则直接返回,不需要再次进行计算,因为String是被final修饰的,它不会被修改,所以没有必要每次都重新计算hash值。

public int hashCode() {//首先从String的成员变量hash获取到hash值int var1 = this.hash;//如果hash值为0且当前String不为空if (var1 == 0 && this.value.length > 0) {//获取到当前String的char[]char[] var2 = this.value;//逐个使用char循环叠加计算hash值for(int var3 = 0; var3 < this.value.length; ++var3) {var1 = 31 * var1 + var2[var3];}//计算好后将hash值赋值给成员变量hashthis.hash = var1;}//最后返回hash值return var1;
}

compareTo方法
通过两个字符串的第一个不一样的字符来比较大小并返回结果,若两个字符串的字符都一样则比较两个字符串的长度。

public int compareTo(String str) {//分别获取到当前String和传入String的lengthint thisLen = this.value.length;int strLen = str.value.length;//计算出两个String最小的长度minLenint minLen = Math.min(thisLen, strLen);char[] thisValue = this.value;char[] strValue = str.value;//循环找出两个字符串第一个不一样的字符比较大小并返回比较结果for(int i = 0; i < minLen; ++i) {char thisChar = thisValue[i];char strChar = strValue[i];if (thisChar != strChar) {return thisChar - strChar;}}//若两个字符串循环比较的字符是一样的,那么使用字符串长度来比较大小return thisLen - strLen;
}

String源码解析相关推荐

  1. Java String源码解析

    String类概要 所有的字符串字面量都属于String类,String对象创建后不可改变,因此可以缓存共享,StringBuilder,StringBuffer是可变的实现 String类提供了操作 ...

  2. Java的String为什么不可变?(String源码解析)

    String的源码解析 public final class String{private final char value[];//容器,存放字符串的private int hash;//哈希值pr ...

  3. Java - String源码解析及常见面试问题

    文章目录 Pre Q1: String 是如何实现的? Q2: String 有哪些重要的方法? 构造函数 equals() compareTo() [equals() vs compareTo() ...

  4. String 源码解析

    类的定义 public final class Stringimplements java.io.Serializable, Comparable<String>, CharSequenc ...

  5. string 长度_String源码解析

    本章源码分析基于JDK1.7 实现的接口 String类被final修饰词修饰,代表不可修改的特性,它实现了三个接口,Serializable是序列化接口,Compareble是排序接口,Char是字 ...

  6. 面试官系统精讲Java源码及大厂真题 - 02 String、Long 源码解析和面试题

    02 String.Long 源码解析和面试题 劳动是一切知识的源泉. --陶铸 引导语 String 和 Long 大家都很熟悉,本小节主要结合实际的工作场景,来一起看下 String 和 Long ...

  7. String str = new String(abc)创建了几个对象?结合源码解析

    String str = new String("abc")创建了几个对象?结合源码解析 首先,我们看一下jdk源码: 1 /** 2 * Initializes a newly ...

  8. Redis源码-String:Redis String命令、Redis String存储原理、Redis String三种编码类型、Redis字符串SDS源码解析、Redis String应用场景

    Redis源码-String:Redis String命令.Redis String存储原理.Redis String三种编码类型.Redis字符串SDS源码解析.Redis String应用场景 R ...

  9. String为什么不可变?(Java源码解析)

    String的源码解析 public final class String{private final char value[];//容器,存放字符串的private int hash;//哈希值pr ...

最新文章

  1. 当网络安全遇上大数据分析(9)
  2. Java复习-线程之间的通信与同步
  3. Cocos2d-x 在缓存创建图片
  4. unity3d collider自动调整大小_自动网格组合建模工具Unity游戏素材资源
  5. flask框架+mysql数据库并与前台数据交互
  6. 史蒂夫 乔布斯(Steve Jobs)在斯坦福大学2005年毕业典礼上的演讲
  7. P4878 道路修建-美国
  8. 背景裁剪图片html,HTML5基础加强css样式篇(文本裁剪,背景裁剪:background-origin,background-position,background-clip)(三十七)...
  9. ios 仿微信,短信聊天气泡
  10. 2013计算机二级试题,2013年3月全国计算机二级VFP真题
  11. 如何修改apache 2最大连接数
  12. java 范型 隐式 显式_隐式与显式接口实现
  13. 【VS2010学习笔记】【异常处理】general error c1010070: Failed to load and parse the manifest.
  14. 虚拟机访问服务器文件夹,浅析CentOS8虚拟机访问Windows10主机文件夹方法
  15. ISO27001的认证周期及流程
  16. 利用Openyxl为Excel批量插入表头行(Excel读写基础操作)——下
  17. ThinkPad 声卡出现未安装任何音频输出设备
  18. python银行家算法例题详解_攒人品之作-能考408大题的知识点整理(有两个知识点的补充)...
  19. CAD梦想画图中的“线型设置”
  20. 燕京理工学院计算机答辩难吗,燕京理工学院:一腔热血答与辩,满腹经纶方成功...

热门文章

  1. leetCode-995:K 连续位的最小翻转次数
  2. 【前端基础知识】chrome安装React Devtools
  3. qtitanribbon注册_点云平台之QtitanRibbon
  4. pip指定源安装_几种python安装简单方法
  5. android编程多组件布局,Android把多个控件定义成一个整体的布局类使用
  6. server接收dtu透传代码_ESP8266 STM32 HTTP json透传实验
  7. 灰色预测模型matlab_Matlab数据分析,2020研究生报名人数灰色预测
  8. vscode 崩溃_太真实了!程序员崩溃的40个瞬间
  9. delphi php 加密解密_如何恢复被MaMoCrypt勒索软件加密的数据
  10. c语言程序40例,C语言程序讲解40例.pdf