源码阅读篇-String类

Java的String

1.简介

学习一下 java.lang.String类的方法和源码

2.作用和特性

 只有一个父类就是Object 所有Java类都是继承于Object类
 实现了三个接口:Serizable 序列化接口,CharSequence(char的可读序列),Comparable<T>排序接口

String 代表字符串,在创建后不可变。
被final修饰 俗称的断子绝孙类 >_< 不能被继承

本质是字符数组:

      String str="abc";

相当于:

   char data[] = {'a', 'b', 'c'};
   String str = new String(data);   

2.1 成员变量

成员变量

见图知意:注意都是final修饰的

value[] :

     用来存储组成字符串的字符数组
     使用了private,也没有提供setter方法,所以在String类的外部不能修改value,
      同时value也使用了final进行修饰,那么在String类的内部也不能修改value

hash:

 存储的是String的hash值 就是散列码 具体算法下面hashcode方法

PS:

final在修饰引用类型变量时,表示该引用在构造对象之后不能指向其他的对象
但该引用指向的对象的状态可以改变
关键是因为SUN公司的工程师,在后面所有String的方法里都很小心的没有去动字符数组里的元素。
所以String类不可变的关键都在底层的实现,而不仅仅是一个final

3.构造方法(弃用的构造方法不赘述了)

 1.String() 初始化新创建的 String对象,使其表示空字符序列。 

 2.String(byte[] bytes,Charset charset):根据指定的字节的数组解码charset创建一个新的String 。

 3.String(byte[] bytes, int offset, int length):和上面一样不过指定了字节数组的长度和起始位置

 4.String(byte[] bytes, int offset, int length, String charsetName) 

 5.String(byte[] bytes, String charsetName) :见参数知意

 6.String(char[] value):见参数知意 

 7.String(char[] value, int offset, int count) :见参数知意

 8.String(int[] codePoints, int offset, int count) :分配一个新的 String ,其中包含 Unicode code point数组参数的子阵列中的 字符 。 

 9.String(String original) :根据指定的字符串 初始化一个字符串对象 新的字符串的hash值和value字符数粗的值是一样的

 10.String(StringBuffer buffer) : 根据StringBuffer生成String

 11.String(StringBuilder builder)  : 根据StringBuilder 生成String 区别是StringBuffer的 length方法是线程安全的

3.1 涉及到String的基本原理的方法:arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

 java.lang.System 类 (这个类不能被实例化就是说不能new 他的构造方式是private)下得到方法:

 arraycopy(Object src, int srcPos, Object dest, int destPos, int length) :

 将指定源数组中的数组从指定位置复制到目标数组的指定位置。

 参数:
    src:要被拷贝的数组对象  srcPos:要被拷贝数组的起始位置  dest:新的数组  destPos:新的数组存储的起始位置  length:要拷贝的数组长

举了例子:

    public static void main(String[] args) {
        int[] a = new int[]{1, 4, 5, 6};
        int[] b = new int[4];

        System.out.println( Arrays.toString( a ) );
        System.out.println( Arrays.toString( b ) );
        /**
         * 从数组a的第2个元素开始拷贝到b 从b的第二个元素开始写入  长度为3
         * 注意:1 这是指 数组的下标索引 而数组都是从0开始的
         */
        System.arraycopy( a,1,b,1,3 );
        System.out.println( "——————————数组拷贝后输出————————————");
        System.out.println( Arrays.toString( a ) );
        System.out.println( Arrays.toString( b ) );
    }

输出结果:
        
        [1, 4, 5, 6]
        [0, 0, 0, 0]
        ——————————数组拷贝后输出————————————
        [1, 4, 5, 6]
        [0, 4, 5, 6]

4.常用方法

4.1 charAt(int index):

   返回指定索引处的字符值 记住String本质是字符数组构建的 所以索引下标都是从0开始

4.2 compareTo(String anotherString) :

      按照字典序与指定的字符串比较 返回结果:相等-0  参数在String之前返回>0 反之小于0

       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) {                //从0开始 相同索引处的字符开始比较 如果都是相等的一直到到 最小长度
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;      //返回 比较结果
            }
            k++;
        }
        return len1 - len2;   //如果没个字符都相等 返回长度比较值 还是相等 那么就是相等
    }
PS:这个方法大小写敏感  compareToIgnoreCase(String str) :这个方法忽略大小写比较

4.3 concat(String str) :

    把指定的字符串 连接到字符串的末尾  字符串四大拼接方式之一

源码:

      public String concat(String str) {
      int otherLen = str.length();  //获取指定字符串的长度属性
      if (otherLen == 0) {            //如果长度为0 返回当前这个字符串即可
          return this;
      }
      int len = value.length;          //获取当前字符串的长度属性
     //字符数组拷贝一个新的数组 注意这就是字符串不可变的根本原因 不是简单的final修饰一句话概括 
      char buf[] = Arrays.copyOf(value, len + otherLen);   
      str.getChars(buf, len);
      return new String(buf, true);   //构造一个新的字符串返回 
  }   

4.4 length() :返回此字符串的长度。

length方法源码

很简单直白就是返回字符数组的长度

4.4 equals(Object object) :比较对象是否相等。

比较方法源码

4.5 hashCode():、

字符串hash值算法
数学公式:val[0]31^(n-1) + val[1]31^(n-2) + ... + val[n-1] n是数组长度
具体系数为什么选择31 粗浅的理解: 31是一个素数 31可以表示二进制位 11111-1 只占用5个字节 散列性比较好 而且不容易造成溢出 丢失精度 据说很多虚拟机都是31做了优化

4.5substring(int beginIndex, int endIndex)

原理:

substring源码
JDK6和JDK7之后这个方法的区别
  JDK6 是在堆空间创建新的String对象 但是不创建新的数组   

    数组还是采用原来的数组 和原来String对象区别是String的成员变量 offset字符数组开始下标和count数组长度改了 

    但是原来的数组还在  问题因为这个非常长的字符数组一直在被引用,所以无法被回收,就可能导致内存泄露 

    解决方法方法  substring(int beginIndex, int endIndex)+“” 这样就能创建一个新的数组

  JDK7  以后直接新建一个数组  让原来的数组不被引用 让垃圾回收清理掉

4.6 replace(),replaceAll()、replaceFist()的原理和区别

replace源码
 replaceFirst(): 正则匹配 只替换匹配到的第一个 用StringBuffer做的替换
 replaceAll()    正则匹配替换 全部 用StringBuffer做的替换
 replace()方法原理:![replace源码]

4.7 String 对“+”的重载的两种情况:

         1.String s1 = "yves"; String s2 = s1 + "he";等于 String s1 = "yves";    

           String s2 = (new StringBuilder(String.valueOf(s1))).append("he").toString();

         2.String s1 = "yves" + "he";  这种JDK 会自动优化处理 “yveshe”

   字符串拼接的四种方式:

         plus 所谓"+"号 拼接:  效率低下 每次拼接都会创建一个 StringBuilder对象 多次拼接会创建大量对象

         concat拼接 :concat其实就是声明一个char类型的buf数组,将需要拼接的字符串都放在这个数组里,最后再转换 

                      成String对象 本质还是数组的拷贝  concat是要多少扩容多少 扩容效率低下

         StringBuilder/StringBuffer append方法: 调用父类AbstractStringBuilder的append方法,

                       而 StringBuffer是的append方法加了sychronized关键字,因此是线程安全的  

                       本质还是数组的拷贝 和 concat区别是数组的扩容 这两个是指数级扩容 

         效率:StringBuilder>StringBuffer >concat>plus  

               StringBuilder线程不安全 没加锁 StringBuffer线程安全加了锁 concat扩容机制低下 plus需要创建对象
StringBuilder扩容原理
需要扩容的的时候直接扩大2倍+2 MAX_ARRAY_SIZE定义是 Integer.MAX_VALUE - 8 应该是21亿多(2^31 -1 -8)

4.8 特殊的方法:String intern()

这是一个原生的方法:

image.png

简单来说就是 如果字符串常量池中有新建的字符串 调用这个方法会直接去找一次字符常量池 如果有直接指向常量池的地址 没有的话就新建一个String对象
字符串内存测试

public static void main(String[] args) {
        String  str1="Java";

        String  str2 = new String( "Java" );

        System.out.println("Str1==Str2:"+(str1==str2));

        String  str3 = new String( "Java" ).intern();

        System.out.println("Str1==Str3:"+(str1==str3));

    }
结果:
  Str1==Str2:false
  Str1==Str3:true
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,766评论 0 38
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,339评论 0 2
  • 一、基本数据类型 注释 单行注释:// 区域注释:/* */ 文档注释:/** */ 数值 对于byte类型而言...
    龙猫小爷阅读 4,257评论 0 16
  • 烈火白裘的少年你想要闲话夕阳 一串一串的星光接不住的 大地把你的骏马雪藏了的 火红的天所向披靡 风里雨里走着跑着的...
    沐枫集阅读 239评论 0 3
  • 出租车司机这个工作每天都能见到形形色色的人,不同阶级,不同年龄。 所以,我觉得他们的工作也挺有意思的,听着一个乘客...
    叙事簿阅读 374评论 0 0