String类的签名(JDK 8):

  public final class String implements java.io.Serializable, Comparable<String>, CharSequence { }

  String是不可变类,即String对象也是不可变对象。

  这意味着当修改一个String对象的内容时,JVM不会改变原来的对象,而是生成一个新的String对象。

 一、CharSequence 接口

  CharSequence API 解释,CharSequence的实例是一个包含“一个或者多个字符值(char values)”的可读序列。这个接口的功能就是对不同种类的字符序列提供统一的只读访问。

  CharSequence的实现类有String,StringBuffer,StringBuilder等。

  CharSequence接口要求实现的方法如下:

二、String类的字段

  2.1 private final char value[];

  存储组成字符串值的字符数组value,也是不可变的。

  

  2.2 private int hash;

  缓存String实例的hash值

  2.3 private static final long serialVersionUID = -6849794470754667710L;

  这个没太懂,注释解释如下:

  use serialVersionUID from JDK 1.0.2 for interoperability(互操作性)

  2.4 private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];

  注释解释:Class String is special cased within the Serialization Stream Protocol

  StackOverflow上有讨论:why String in java does not override readObject?

  Strings, arrays and enums are special cases in serialization, and are not serialized through readObject/writeObject like other Objects are.

  Java中,字符串、数组和枚举在序列化方面是特殊的类,他们没有像其他对象一样通过readObject/writeObject进行序列化。

  2.5 public static final Comparator<String> CASE_INSENSITIVE_ORDER= new CaseInsensitiveComparator();

  CaseInsensitiveComparator类是一个String类中自己实现的比较器类。

  这个比较器对象通过compareToIgnoreCase对String对象进行排序的比较器。compareToIgnoreCase是String类中方法,功能是按字典顺序比较两个字符串,忽略大小写差异。返回正值,0,或者负值。

  该比较器是可序列化的。

  三、构造函数

  划线的表示本版JDK中已经被抛弃的。

  

  

  四、源自CharSequence接口的方法

  这些方法功能很明确,实现也并不复杂。

  

  五、源自Comparable的方法

  public int compareTo(String anotherString)

  按字典顺序比较两个字符串(上面有个字段也与比较有关,但与这个函数没有关系),这个是大小写敏感的,而且返回值也不是简单地以正负值表示比较结果。

  直接上源码:

public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value; int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}

  当String 的equals方法返回true时,该方法返回0.

  至于字典序到底怎么算大小,可以总结一下:

  小写字母>大写字母;同大小写,越靠字母表后面越大。

  ps:看完这个源码,我产生了疑惑,同一个类的不同实例竟然可以相互访问各自的private成员!!??

  是的,确实可以!!

  六、其它重要方法

  1、substring()——public String substring(int beginIndex);

public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}

  sublen是索要生成的子串的长度,这个函数生成的子字符串为从内部的value字符数组中索引为beginIndex处到末尾处字符组成的字符串。

  如果beginIndex为0,则返回字符串本身;
  如果beginIndex不为0,则返回new String(value, beginIndex, subLen)
  下面上构造函数String(char value[], int offset, int count)源码:

public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}

  方法最后返回的是Arrays.copyOfRange(value, offset, offset+count),继续跟踪:

public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}

  System.arraycopy()方法是一个native方法,它将指定源数组src中的数组从指定位置srcPos开始复制到目标数组dest的指定位置destPos,而length是所复制的长度。

public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos, int length)

  newLength是要复制的长度,copy是根据这个长度新建的char数组。这个copy将作为新建子串的value值。

  

  2、substring()——public String substring(int beginIndex, int endIndex)

public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > value.length) {
throw new StringIndexOutOfBoundsException(endIndex);
}
int subLen = endIndex - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return ((beginIndex == 0) && (endIndex == value.length)) ? this
: new String(value, beginIndex, subLen);
}

  基本一样,subLen是根据endIndex和beginIndex得到的子串长度,需要注意endindex索引处的字符不包含在子串中。

Java String类源码的更多相关文章

  1. java.lang.String 类源码解读

    String类定义实现了java.io.Serializable, Comparable<String>, CharSequence 三个接口:并且为final修饰. public fin ...

  2. Java Properties类源码分析

    一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...

  3. String 类源码分析

    String 源码分析 String 类代表字符序列,Java 中所有的字符串字面量都作为此类的实例. String 对象是不可变的,它们的值在创建之后就不能改变,因此 String 是线程安全的. ...

  4. java String部分源码解析

    String类型的成员变量 /** String的属性值 */ private final char value[]; /** The offset is the first index of the ...

  5. java Character类源码分析

    一.使用 构建Character对象: public class CharTest { public static void main(String[] args) { Character c1 = ...

  6. String类源码分析(JDK1.7)

    以下学习根据JDK1.7String类源代码做注释 public final class String implements java.io.Serializable, Comparable<S ...

  7. String类源码分析

    1.String类注释说明 /** * The {@code String} class represents character strings. All * string literals in ...

  8. String类源码解析

    1. String是使用char[]数组来存储的,并且String值在创建之后就不可以改变了.char[]数组的定义为: /** The value is used for character sto ...

  9. Java集合---Array类源码解析

    Java集合---Array类源码解析              ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...

随机推荐

  1. 关系型数据库的树形结构查询(Oracle、Postgres)

    Oracle : start with… connect by 的用法.语法:select * from table [where 条件1] connect by[条件2] start with[条件 ...

  2. Dubbo系列(三)dubbo的核心技术--RPC调用

    dubbo的核心技术--RPC调用:分为俩部分RPC协议Protocol和方法调用Invoke: 一.RPC协议Protocol(Remote Procedure Call)远程过程调用协议 1.我们 ...

  3. HearthBuddy Ai调试实战1-->出牌的时候,少召唤了图腾就结束回合

    期望通过ai的调试,来搞明白出牌的逻辑. 55是投火无面者63是恐狼前锋34是风怒36是自动漩涡打击装置13是空灵召唤者, "LocStringZhCn": "<b ...

  4. Flutter移动电商实战 --(38)路由_Fluro中Handler编写方法

    在main.dart中初始化Fluro 编写handler 在lib下新建routers文件夹,表示里面要很多路由相关的文件 我们声明一个Handler,在里面handlerFunc固定的两个参数 重 ...

  5. zookeeper-3.5.5安装报错:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/jiangxiulilinux/artic ...

  6. 003-log-jul,jdk自带日志服务

    一.简介 java官方日志jul,位于java.util.logging包下. 1.1.POM依赖 无依赖 1.2.配置 JUL的默认配置文件是logging.properties ,在 $JAVA_ ...

  7. 修改ssh端口

    centos7.5修改默认SSH端口 linux SSH默认端口是22,不修改的话存在一定的风险,要么是被人恶意扫描,要么会被人破解或者攻击,所以我们需要修改默认的SSH端口 1.修改22端口为620 ...

  8. Centos7系统下以RPM方式如何安装mysql-5.7

    检查系统是否装有mariadb rpm -qa | grep mariadb 卸载mariadb 强制卸载mariadb rpm -e --nodeps mariadb-libs-5.5.35-3.e ...

  9. 【Python】机器学习之单变量线性回归 利用批量梯度下降找到合适的参数值

    [Python]机器学习之单变量线性回归 利用批量梯度下降找到合适的参数值 本题目来自吴恩达机器学习视频. 题目: 你是一个餐厅的老板,你想在其他城市开分店,所以你得到了一些数据(数据在本文最下方), ...

  10. 【并行计算-CUDA开发】 NVIDIA Jetson TX1

    概述 NVIDIA Jetson TX1是计算机视觉系统的SoM(system-on-module)解决方案.它组合了最新的NVIDIAMaxwell GPU架构,其具有ARM Cortex-A57 ...