用了好久的Java了,从来没有看过jdk的源码,趁着今天有点时间,拿出了jdk的源码看了下,今天先看了关于String的,毕竟开发中String类型使用最广泛。在我们下载安装jdk的时候,部分源码也已经同时存放在我们电脑里了,具体路径为jdk目录下的src.zip压缩包,解压即可。

java.lang.String

1 public final class String 2 implements java.io.Serializable, Comparable<String>, CharSequence

这是String类的声明,很明显它是由final类型声明的,所以它不能被继承,而它又实现了Serializable接口,代表它是可以被序列化的。

接着我们来看看类内部是怎么定义的

/** The value is used for character storage. */private final char value[];

使用final类型的字符数组存储字符串内容,String初始化后就不能被改变。

有一种写法,String s = “abc”; s = “bcd”;当然这并不是改变了字符串s的值,只是将s指向了一个新的字符串,所以千万不要以为字符串是可以变的。

/** Cache the hash code for the string */private int hash; // Default to 0

指定缓存字符串的hash code的值,默认为0

/** use serialVersionUID from JDK 1.0.2 for interoperability */private static final long serialVersionUID = -6849794470754667710L;

相当于java类的身份证。主要用于版本控制。serialVersionUID作用是序列化时保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。有两种生成方式:       一个是默认的1L,比如:private static final long serialVersionUID = 1L;       一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如:       private static final long serialVersionUID = xxxxL;
/*** Class String is special cased within the Serialization Stream Protocol.** A String instance is written into an ObjectOutputStream according to* <a href="{@docRoot}/../platform/serialization/spec/output.html">* Object Serialization Specification, Section 6.2, "Stream Elements"</a>*/private static final ObjectStreamField[] serialPersistentFields =new ObjectStreamField[0];

serialPersistentFields 用于指定哪些字段需要被默认序列化,如:
private static final ObjectStreamField[] serialPersistentFields =
{  new ObjectStreamField("name", String.class),   new ObjectStreamField("a", Integer.TYPE)
}; 

看了String类的构造方法,惊叹不已,源码中有足足15种构造方法,其中最常用的不外乎以下几种
public String(byte bytes[]) {this(bytes, 0, bytes.length);}
public String(StringBuffer buffer) {synchronized(buffer) {this.value = Arrays.copyOf(buffer.getValue(), buffer.length());}}
public String(StringBuilder builder) {this.value = Arrays.copyOf(builder.getValue(), builder.length());}

再往后看就是String类自身提供的一系列方法了:
// 返回字符串的长度  public int length() {return value.length;}// 字符串是否为空public boolean isEmpty() {return value.length == 0;}// 字符串目标位置的字符public char charAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return value[index];}// 返回指定索引处的字符public int codePointAt(int index) {if ((index < 0) || (index >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return Character.codePointAtImpl(value, index, value.length);}// 返回指定索引之前的字符public int codePointBefore(int index) {int i = index - 1;if ((i < 0) || (i >= value.length)) {throw new StringIndexOutOfBoundsException(index);}return Character.codePointBeforeImpl(value, index, 0);}// 返回此 String 的指定文本范围中的 Unicode 代码点数public int codePointCount(int beginIndex, int endIndex) {if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {throw new IndexOutOfBoundsException();}return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);}
//返回从0处开始的第i个Code Point的位置
public int offsetByCodePoints(int index, int codePointOffset) {if (index < 0 || index > value.length) {throw new IndexOutOfBoundsException();}return Character.offsetByCodePointsImpl(value, 0, value.length,index, codePointOffset);}//判断两个字符串是否相等
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;}//不区分大小写的情况下比较两个字符串是否相等
public boolean equalsIgnoreCase(String anotherString) {return (this == anotherString) ? true: (anotherString != null)&& (anotherString.value.length == value.length)&& regionMatches(true, 0, anotherString, 0, value.length);}
//计算当前字符串比目标字符串长度大多少
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;}

//获取哈希值
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;}
//返回某个指定的字符串值在字符串中首次出现的位置
public int indexOf(int ch) {return indexOf(ch, 0);}
public int indexOf(int ch, int fromIndex) {final int max = value.length;if (fromIndex < 0) {fromIndex = 0;} else if (fromIndex >= max) {// Note: fromIndex might be near -1>>>1.return -1;}if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {// handle most cases here (ch is a BMP code point or a// negative value (invalid code point))final char[] value = this.value;for (int i = fromIndex; i < max; i++) {if (value[i] == ch) {return i;}}return -1;} else {return indexOfSupplementary(ch, fromIndex);}}
//返回某个指定的字符串值在字符串中最后一次出现的位置
public int lastIndexOf(int ch) {return lastIndexOf(ch, value.length - 1);}
public int lastIndexOf(int ch, int fromIndex) {if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {// handle most cases here (ch is a BMP code point or a// negative value (invalid code point))final char[] value = this.value;int i = Math.min(fromIndex, value.length - 1);for (; i >= 0; i--) {if (value[i] == ch) {return i;}}return -1;} else {return lastIndexOfSupplementary(ch, fromIndex);}}
//从指定位置截取字符串直至最后一位
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);}
//截取字符串从beginIndex至beginIndex
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);}

//字符串拼接
public String concat(String str) {int otherLen = str.length();if (otherLen == 0) {return this;}int len = value.length;char buf[] = Arrays.copyOf(value, len + otherLen);str.getChars(buf, len);return new String(buf, true);}
//字符串替换
public String replace(char oldChar, char newChar) {if (oldChar != newChar) {int len = value.length;int i = -1;char[] val = value; /* avoid getfield opcode */while (++i < len) {if (val[i] == oldChar) {break;}}if (i < len) {char buf[] = new char[len];for (int j = 0; j < i; j++) {buf[j] = val[j];}while (i < len) {char c = val[i];buf[i] = (c == oldChar) ? newChar : c;i++;}return new String(buf, true);}}return this;}
//判断字符串是否包含在另一个字符串中
public boolean contains(CharSequence s) {return indexOf(s.toString()) > -1;}
//将目标字符串中匹配的字符全部替换成另一字符串
public String replaceAll(String regex, String replacement) {return Pattern.compile(regex).matcher(this).replaceAll(replacement);}
//按约定分隔符将目标字符串分割成多个字符串并返回字符串数组
public String[] split(String regex, int limit) {/* fastpath if the regex is a(1)one-char String and this character is not one of theRegEx's meta characters ".$|()[{^?*+\\", or(2)two-char String and the first char is the backslash andthe second is not the ascii digit or ascii letter.*/char ch = 0;if (((regex.value.length == 1 &&".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||(regex.length() == 2 &&regex.charAt(0) == '\\' &&(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&((ch-'a')|('z'-ch)) < 0 &&((ch-'A')|('Z'-ch)) < 0)) &&(ch < Character.MIN_HIGH_SURROGATE ||ch > Character.MAX_LOW_SURROGATE)){int off = 0;int next = 0;boolean limited = limit > 0;ArrayList<String> list = new ArrayList<>();while ((next = indexOf(ch, off)) != -1) {if (!limited || list.size() < limit - 1) {list.add(substring(off, next));off = next + 1;} else {    // last one//assert (list.size() == limit - 1);
                    list.add(substring(off, value.length));off = value.length;break;}}// If no match was found, return thisif (off == 0)return new String[]{this};// Add remaining segmentif (!limited || list.size() < limit)list.add(substring(off, value.length));// Construct resultint resultSize = list.size();if (limit == 0) {while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {resultSize--;}}String[] result = new String[resultSize];return list.subList(0, resultSize).toArray(result);}return Pattern.compile(regex).split(this, limit);}

 
 

转载于:https://www.cnblogs.com/timePasser-leoli/p/7873311.html

学习JDK源码(一):String相关推荐

  1. JDK源码阅读 String

      1.String是如何做到不可变?为什么要将它设计为不可变类?     答:首先String类是被final修饰,不能被继承:它把数据存放在一个数组value中,value同样被final修饰:所 ...

  2. 死磕JDK源码之String

    String本质是对char数组的封装 Serializable接口 实现Serializable接口的类可以被序列化 Comparable接口 实现Comparable接口的类可以支持排序,需要重写 ...

  3. [置顶] 学习JDK源码:可进一步优化的代码

    1.参数化类型的构造函数比较啰嗦 new HashMap<String, List<String>>() 如果你调用参数化类的构造函数,那么很不幸,你必须要指定类型参数,即便上 ...

  4. JDK源码学习笔记——String

    1.学习jdk源码,从以下几个方面入手: 类定义(继承,实现接口等) 全局变量 方法 内部类 2.hashCode private int hash; public int hashCode() {i ...

  5. 非常实用,IDEA 搭建JDK源码学习环境(可修改+断点+笔记)

    点击关注公众号,实用技术文章及时了解 来源:chenxiao.blog.csdn.net/article/details/104369824 在学习JDK源码的时候,自然少不了代码的调试. 阅读与调试 ...

  6. 简单工厂 jdk源码解析

    我们看一下简单工厂在JDK源码的一些体现,我们看一个比较熟悉的类,Calendar这么一个类,我们找一个getInstance这么一个方法,public static Calendar getInst ...

  7. 如何更高效地阅读JDK源码

    简介 阅读源码的几个问题: 为什么要看JDK源码 JDK源码的阅读顺序 JDK源码的阅读方法 为什么要看JDK源码 一,JDK源码是其它所有源码的基础,看懂了JDK源码再看其它的源码会达到事半功倍的效 ...

  8. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  9. JDK源码学习-基础

    JDK源码学习 目录 基础 1. 安装 1.1 下载JDK 1.2 配置环境变量 1.3 验证 2. 简单的程序 2.1 编写代码 2.2 编译文件 2.3 执行类 3. java基本类型 基础 1. ...

最新文章

  1. Redis 官方可视化工具,功能强大、干净又卫生!
  2. 【ZJ选讲·字符串折叠】
  3. Vue电商后台B站的项目需要的材料 密码等
  4. python才能做爬虫,No,C#也可以!
  5. 从jsp向servlet传送数据的两种方式
  6. bash: ssh: command not found解决方法
  7. 计算机监控网络运维合同书,网络服务托管运维合同范本
  8. win10 UWP RSS阅读器
  9. 服务器怎么识别swf文件,服务器架设swf支持播放flv格式 swf格式
  10. c语言中power是什么变量,c语言学习新手必看 power by vcok.com[转载]
  11. 海康直连工具 海康测试工具,工程宝测试软件等
  12. 必须收藏!这13个优秀React JS框架,没用过就很离谱!
  13. 直播已入下半场,秀场直播该何去何从?
  14. 改进神经网络的学习方法(上)
  15. 「开源学」:如何分门别类理解开源
  16. qt4.8 利用串口实现智能大棚系统
  17. 如何让soso百科通过
  18. MSI Afterburner(微星显卡超频工具)v4.6.0 中文版
  19. 华为mate30epro是鸿蒙系统吗,华为mate30epro和mate30区别 华为mate30epro和mate30区别在哪 - 云骑士一键重装系统...
  20. 赚钱思考:屌丝逆袭应该怎么开始?

热门文章

  1. 明小子动力上传拿webshell(1).zip
  2. [转]:tbox中数据库的使用
  3. Codeforces Round #350 (Div. 2) B. Game of Robots 水题
  4. maven中net.sf.json报错的解决方法
  5. 谢宝友:会说话的Linux内核
  6. Linux基本管理篇
  7. 进程在linux系统中原理,Linux系统原理知识 进程切换的概念介绍
  8. python3爬虫入门实例_10个python爬虫入门实例(小结)
  9. mysql 2100,MySQL 实现准实时的表级别DML计数
  10. 数据库封装 sql server mysql_mysql操作数据库进行封装实现增删改查功能