String字符串的前世今生

String字符串的前世今生

String是我们最常用的数据类型,不过你真的了解它吗?今天让我们一起了解一下它的前世今生。

源码JDK8

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private int hash;
    private final char value[];
}

源码JDK9之后

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    @Stable
    private final byte[] value;
    private final byte coder;
    private int hash;
}

首先,我们发现String实现了众多接口:

  • 实现了Serializable,意味着可以序列化。
  • 实现了Comparable,意味着可以使用compareTo进行比较。
  • 实现了CharSequence,该接口提供对许多不同类型的char序列的统一。

其次,观察源码String本身和属性value都被final修饰,我们都知道,final修饰类则该类不能被继承,也就是不能有子类,final修饰属性则该属性为常量一旦赋值,则不能改变。

当String本身和value属性都被final修饰,这就使得String具有了不可变性,这样设计的意义何在?

  • 可以保证String对象的安全性,保证存储值不会被恶意修改。
  • 当保证String本身不可变后间接的影响hash值的唯一,从而使String更适合做键值(Map<String,Object>)。
  • 可以用作字符串常量池。

然后,对比JDK8和9,最明显的一个区别就是存储字符的数组怎么由char -> byte,那么为什么要变成使用byte数组存储呢?

因为开发人员发现人们使用的字符串值是拉丁字符居多,而每一个char占用两个字节,如果使用的char数组存储只需要一个字节就OK啦,另外一个字节就会造成浪费了,进而造成内存的浪费,gc的更加频繁,因此在jdk9中将String底层的实现改为了byte数组。
Soga!!!
除此之外,心细的小伙伴已经发现,JDK9之后多出来的coder是个啥玩意啊?

/**
     * The identifier of the encoding used to encode the bytes in
     * {@code value}. The supported values in this implementation are
     *
     * LATIN1
     * UTF16
     *
     * @implNote This field is trusted by the VM, and is a subject to
     * constant folding if String instance is constant. Overwriting this
     * field after construction will cause problems.
     */
    private final byte coder;

coder属性用来表示编码格式,看源码注释发现coder有两个实现LATIN1、UTF16

   @Native static final byte LATIN1 = 0;
   @Native static final byte UTF16  = 1;

除此之外,COMPACT_STRINGS这个属性也是十分重要,翻译为压缩字符串,默认静态代码块赋值true。

/**
     * If String compaction is disabled, the bytes in {@code value} are
     * always encoded in UTF16.
     */
static final boolean COMPACT_STRINGS;
    static {
        COMPACT_STRINGS = true;
    }

注释:如果禁用了字符串压缩,{@code value}中的字节是总是使用UTF16编码,很明显这个就是决定该String对象是否采用压缩策略的关键属性。

最后我们查看构造器

 String(char[] value, int off, int len, Void sig) {
    // 空判断
        if (len == 0) {
            this.value = "".value;
            this.coder = "".coder;
            return;
        }
        // 如果开启压缩字符串策略那么就尝试压缩
        if (COMPACT_STRINGS) {
            byte[] val = StringUTF16.compress(value, off, len);
            if (val != null) {
                this.value = val;
                this.coder = LATIN1;
                return;
            }
        }
        // 如果没有压缩成功并返回就直接设置为UTF16
        this.coder = UTF16;
        this.value = StringUTF16.toBytes(value, off, len);
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值