string 压缩_String 源码浅析

本文深入探讨了String类的源码,重点分析了JDK9中对String的优化,即采用byte[]数组代替char[]以节省内存。文章介绍了String的不可变性、实现的接口以及在JDK6和JDK9中的压缩字符串优化。此外,还总结了String的构造方法和常用API,如concat、format、regionMatches和split函数的用法。
摘要由CSDN通过智能技术生成

如果问你,开发过程中用的最多的类是哪个?你可能回答是HashMap,一个原因就是HashMap的使用量的确很多,还有就是HashMap的内容在面试中经常被问起。

但是在开发过程中使用最多的类其实并不是HashMap类,而是“默默无闻”的String类。假如现在问你String类是怎么实现的?这个类为什么是不可变类?这个类为什么不能被继承?这些问题你都能回答么。本文就从String源代码出发,来看下String到底是怎么实现的,并详细介绍下String类的API的用法。

String源码结构

首先要说明的是本文的源码是以JDK11为基准,选择JDK11的原因是JDK11是一个LTS版本(长期支持版本),没选择现阶段还在广泛使用的JDK8的原因是想在看源码的过程中学习下JDK的新特性。

还有要说下的就是:大家在看源码时一定要注意JDK的版本,因为不同版本的实现有较大的差异。比如说String的实现在高低版本中就差异比较大。如果你是一个博客主,更加要注明代码的版本了,不然读者可能会很疑惑,为什么和自己之前看的不一样。

好了,下面就言归正传来看下String在JDK11中的实现代码。

public final class String implements Serializable, Comparable<String>, CharSequence {
    
   @Stable
   //字节数组,存放String的内容,如果你看的是较低版本的源代码,这个变量可能是char[]类型,这个其实是JDK9开始对String做的一个优化
   //具体是做了什么优化我们下面再讲,这边先卖个关子
   private final byte[] value;
   //也是和String压缩优化有关,指定当前的LATIN1码还是UTF16码
   private final byte coder;
   //哈希值
   private int hash;
   //序列化Id
   private static final long serialVersionUID = -6849794470754667710L;
   //优化压缩开关,默认开启
   static final boolean COMPACT_STRINGS = true;
   private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];
   public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator();
   static final byte LATIN1 = 0;
   static final byte UTF16 = 1;

   //... 下面部分代码省略
 }

从实现的接口看,String类有如下特点:

  • String类被final关键字修饰,因此不能被继承。
  • String的成员变量value使用final修饰,因此是不可变的,线程安全;
  • String类实现了Serializable接口,可以实现序列化。
  • String类实现了Comparable,可以比较大小。
  • String类实现了CharSequence接口,String本质是个数组,低版本中是char数组,JDK9以后优化成byte数组,从String的成员变量value就可以看出来。

这边说一个看源代码的小技巧:看一个类的源代码时,我们先看下这个类实现了哪些接口,就可以大概知道这个类的主要作用功能是什么了。

JDK9对String的优化

这边首先要讲下JDK 9中对String的优化,如果你不了解这块优化点的话,看String的代码时会感到非常疑惑。

背景知识

在Java中,一个字节char占用两个字节的内存空间。在低版本的JDK中,String的内部默认维护的是一个char[]数组,也就是说一个字符串中包含一个字符,这个字符串内部就包含一个相应长度的字符数组。这样就会出现下面这种情况:

String s = "ddd";
String s1 = "自由之路";

上面两个字符串内部的情况实际上是:

char[] value = ['d','d','d'];
char[] value1 = ['自','由','之','路'];

对于字符串s,我们发现其中每个字符其实都是可以用一个字节表示的,而现在使用两个字符的char类型来表示,明显就浪费了一倍的内存空间。

而且根据统计,在实际程序运行中&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值