先看构造器:

  1.  
  1. private final char value[]; //char类型的数组 以下均会用到
  1. private int hash; //缓存字符串的哈希值 //以下均会用到
  1. public String() {
  2. this.value = "".value; //声明时没有参数 则直接用空.value获取该value值,这个.value不太懂,个人认为应该是类似是将一个整体字符串,分割成char类型数组的方法。
  3. }
  1. public String(String original) {
  2. this.value = original.value; //当存在值的时候 就将该值放到value中,也就是char类型的数组
  3. this.hash = original.hash; //以及对应的哈希值
  4. }
  1. public String(char value[]) { //这个构造器说明了 String其实就是一个char类型的数组
  2. this.value = Arrays.copyOf(value, value.length);
  3. }
  1. public String(char value[], int offset, int count) { //给定起始下标和指定位数的构造器
  2. if (offset < 0) { //先判断给定下标值是否符合逻辑,小于0则报字符串下标越界异常
  3. throw new StringIndexOutOfBoundsException(offset);
  4. }
  5. if (count <= 0) {
  6. if (count < 0) { //再判断截取的位数是否符合逻辑,小于0同样包异常
  7. throw new StringIndexOutOfBoundsException(count);
  8. }
  9. if (offset <= value.length) { //如果起始下标小于等于字符数组长度,那么这个字符数组达不到截取的长度,直接返回空即可。
  10. this.value = "".value;
  11. return;
  12. }
  13. }
  14. // Note: offset or count might be near -1>>>1.
  15. if (offset > value.length - count) { //如果起始位置大于字符数组总长度减去截取长度也会报异常
  16. throw new StringIndexOutOfBoundsException(offset + count);
  17. }
  18. this.value = Arrays.copyOfRange(value, offset, offset+count);
  19. }

其他的构造参数也就类似以上四种,就不再一一列举。

然后就是比较常用的equals

  1. public boolean equals(Object anObject) {
  2. if (this == anObject) { //判断调用对象和传入对象的地址是不是一样的 如果一致则直接判断相同
  3. return true;
  4. }
  5. if (anObject instanceof String) { //如果地址值不相同 则判断传入参数是否属于String类型
  6. String anotherString = (String)anObject; //属于的话进行强转
  7. int n = value.length;
  8. if (n == anotherString.value.length) { //判断转成字符串格式的传入参数长度是否跟要比较的字符串长度一样,不一样则直接返回false
  9. char v1[] = value;
  10. char v2[] = anotherString.value;
  11. int i = 0;
  12. while (n-- != 0) { //长度一样的情况下,将两个字符串生成的字符数据挨个进行对比,用的其实还是==或者!=的方法,有一个不等于则返回false。
  13. if (v1[i] != v2[i])
  14. return false;
  15. i++;
  16. }
  17. return true; //只有两个字符数字完全比较完,没有不相同的才会返回true
  18. }
  19. }
  20. return false;
  21. }

截取字符串substring

  1. public String substring(int beginIndex) {
  2. if (beginIndex < 0) { //判断开始下标是否合理
  3. throw new StringIndexOutOfBoundsException(beginIndex);
  4. }
  5. int subLen = value.length - beginIndex; //比较字符串长度跟起始下标相减得到想要截取的长度 判断是否大于0,不大于则代表数组越界
                                    //个人感觉直接判断起始下标跟总长度-1不就可以吗?可能是需要截取的长度本来就要用,所以直接拿截取长度跟0作比较了)
  6. if (subLen < 0) {
  7. throw new StringIndexOutOfBoundsException(subLen);
  8. }
  9. return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); //如果截取起始下标为0,那就还返回整个字符串,如果不是则返回一个新字符串。
  10. }

StringBuilder的部分源码,进行比较。还是先从构造器看起

  1. public StringBuilder() {
  2. super(16); //下面有super的解释
  3. }
  1. AbstractStringBuilder(int capacity) {
  2. value = new char[capacity]; //由此可以看出 Stringbuilder也是一个字符数组 不过有给定初始长度 长度为6
  3. }

带有指定长度的构造器,跟第一个一样,不过初始长度改为指定值

  1. public StringBuilder(int capacity) {
  2. super(capacity); //初始长度改为参数值
  3. }

第三个,给定一个字符串为参数

  1. public StringBuilder(String str) {
  2. super(str.length() + 16); //给定字符串的长度加16作为初始长度。
  3. append(str); //并将其拼接 拼接的方法在AttributeStringBuilder中
  4. }
  1. public AbstractStringBuilder append(String str) {
  2. if (str == null)
  3. return appendNull(); //如果该字符为空 则返回appendNull()方法,以下有详解
  4. int len = str.length();
  5. ensureCapacityInternal(count + len); //拿到一个足够容量大小的值
  6. str.getChars(0, len, value, count);
  7. count += len;
  8. return this;
  9. }
  1. private AbstractStringBuilder appendNull() {
  2. int c = count;
  3. ensureCapacityInternal(c + 4); //count是计算已经使用的字符个数的 同样也需要拿到一个足够大小的容量值
  4. final char[] value = this.value;
  5. value[c++] = 'n';
  6. value[c++] = 'u';
  7. value[c++] = 'l';
  8. value[c++] = 'l';
  9. count = c;
  10. return this;
  11. }
  1. private void ensureCapacityInternal(int minimumCapacity) { //这个参数就是 上面的c+字符串的长度
  2. // overflow-conscious code
  3. if (minimumCapacity - value.length > 0) { //如果已经使用的字符数加上字符串的长度大于整个字符数组的长度,那么就需要进行扩容了。
  4. value = Arrays.copyOf(value,
  5. newCapacity(minimumCapacity)); //扩容时将之前的字符数组复制到一个新容量的字符数组中,从而保持原来的数据不会丢失
  6. }
  7. }
  1. private int newCapacity(int minCapacity) {
  2. // overflow-conscious code
  3. int newCapacity = (value.length << 1) + 2; //先拿到原字符数组长度一半相加再加2
  4. if (newCapacity - minCapacity < 0) { //进行判断,看看扩容的值够不够大,没有给定的值大,那就用给定的值。
  5. newCapacity = minCapacity;
  6. }
  7. return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) //扩容之后的长度小于等于0或者扩容之后的长度大于数组最大值
  8. ? hugeCapacity(minCapacity) //就需要看这个方法了
  9. : newCapacity;
  10. }
  1. private int hugeCapacity(int minCapacity) {
  2. if (Integer.MAX_VALUE - minCapacity < 0) { // overflow //超过最大值就内存溢出
  3. throw new OutOfMemoryError();
  4. }
  5. return (minCapacity > MAX_ARRAY_SIZE) //大于数组最大值就用给定的值,如果小于数组最大值,那就用数组最大值。
  6. ? minCapacity : MAX_ARRAY_SIZE;
  7. } 

学习String源码的部分方法的更多相关文章

  1. 我该如何学习spring源码以及解析bean定义的注册

    如何学习spring源码 前言 本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人.文章总体难度不大,但比较繁重,学习时一定要耐住 ...

  2. String源码学习

    String源码学习 零散的收获 数组的元素类型可以通过getComponentType来获取到 子类型的数组可以赋值给父类型的数组,.但是并不存在继承关系.数组的父类是Object. 通过声明如下代 ...

  3. 基于JDK1.8的String源码学习笔记

    String,可能是学习Java一上来就学习的,经常用,但是却往往只是一知半解,甚至API有时也得现查.所以还是老规矩,倒腾源码. 一.java doc 这次首先关注String的doc,因为其实作为 ...

  4. 分享学习 PHP 源码的方法

            ​每天抽一点时间来看看 PHP 源码方面的书,说实话,无法在调试器下观察 PHP 运行状态的上下文实在是一件痛苦的事情.不过还好不是一无所获,虽然内容比较多,但是掌握方法挨着看下去还是 ...

  5. 【菜鸟学习jquery源码】数据缓存与data()

    前言 最近比较烦,深圳的工作还没着落,论文不想弄,烦.....今天看了下jquery的数据缓存的代码,参考着Aaron的源码分析,自己有点理解了,和大家分享下.以后也打算把自己的jquery的学习心得 ...

  6. DotNetty网络通信框架学习之源码分析

    DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...

  7. 学习 vue 源码 -- 响应式原理

    概述 由于刚开始学习 vue 源码,而且水平有限,有理解或表述的不对的地方,还请不吝指教. vue 主要通过 Watcher.Dep 和 Observer 三个类来实现响应式视图.另外还有一个 sch ...

  8. String 源码浅析————终结篇

    写在前面 说说这几天看源码的感受吧,其实 jdk 中的源码设计是最值得进阶学习的地方.我们在对 api 较为熟悉之后,完全可以去尝试阅读一些 jdk 源码,打开 jdk 源码后,如果你英文能力稍微过得 ...

  9. 程序兵法:Java String 源码的排序算法(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 <程序兵法:Java Str ...

随机推荐

  1. 常用的正则表达式@java后台

    package Regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @作者 Goofy * @邮件 ...

  2. 基于Java+Spring Boot开源项目JeeSite的Jenkins持续交互介绍

    一.实战项目介绍- JeeSite 基于Spring Boot 2.0 数据存储MySQL 语言:Java 规模大小:适中,适合初学者 源码地址:https://gitee.com/thinkgem/ ...

  3. Spring(IOC、AOP和事务)

    目录 Spring介绍 Spring IOC 传统代码对象管理的弊端 实现过程 bean标签属性介绍 对象创建方式 工厂bean bean的作用域 SpringBean的生命周期*** 依赖注入 注解 ...

  4. PTA甲级—STL使用

    1051 Pop Sequence (25分) [stack] 简答的栈模拟题,只要把过程想清楚就能做出来. 扫描到某个元素时候,假如比栈顶元素还大,说明包括其本身的在内的数字都应该入栈.将栈顶元素和 ...

  5. Codeforces750E. New Year and Old Subsequence (线段树维护DP)

    题意:长为2e5的数字串 每次询问一个区间 求删掉最少几个字符使得区间有2017子序列 没有2016子序列 不合法输出-1 题解:dp i,p(0-4)表示第i个数匹配到2017的p位置删掉的最少数 ...

  6. 【noi 2.6_7627】鸡蛋的硬度(DP)

    题意:其中n表示楼的高度,m表示你现在拥有的鸡蛋个数. 解法:f[i][j]表示 i 层楼有 j 个鸡蛋时,至少要扔多少次.3重循环,k为测试的楼层,分这时扔下去的鸡蛋碎和不碎的情况.要注意初始化. ...

  7. codeforces251A. Points on Line

    Little Petya likes points a lot. Recently his mom has presented him n points lying on the line OX. N ...

  8. VJ train1 I-彼岸

    一道递推题(我这个菜鸡刚开始以为是排列组合) 题目: 突破蝙蝠的包围,yifenfei来到一处悬崖面前,悬崖彼岸就是前进的方向,好在现在的yifenfei已经学过御剑术,可御剑轻松飞过悬崖.现在的问题 ...

  9. POJ1087 A Plug for UNIX(网络流)

    在会议开始之前,你收集所有记者想要使用的设备,并尝试设置它们.你注意到有些设备使用没有插座的插头.你想知道这些设备是否来自建造这个房间时并不存在的国家.对于一些插座,有几个设备使用相应的插头.对于其他 ...

  10. c++派生类中构造函数和析构函数执行顺序、判断对象类型、抽象类、虚函数

    一. 代码: 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include&l ...