资讯专栏INFORMATION COLUMN

String源码解读

zebrayoung / 2090人阅读

摘要:定义是类型,表示该类不能继承,同时实现了三个接口。的序列化机制是通过在运行时判断类的来验证版本一致性。将源字符数组数据一一复制到中的字符数组中。可以通过来解码指定的数组,将其解码成的数组,构造。

String是常量,在定义之后不能被改变,字符串缓冲区支持可变的字符串。因为String对象是不可变的,所以可以共享。

定义
public final class String implements java.io.Serializable, Comparable, CharSequence{}

String 是final类型,表示该类不能继承,同时实现了三个接口java.io.Serializable, Comparable, CharSequence

属性
 private final char value[];

final类型的字符数组,用来存储字符串的内容,因为被final修饰,所以String一旦初始化之后是不能被更改的。

  private int hash;

缓存的hashCode值,默认为0。

  private static final long serialVersionUID = -6849794470754667710L;
   
  private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];

String实现了Serializable接口,所以支持序列化和反序列化。

java 的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性。在进行反序列化时,JVM会把传过来的字节流中的serialVersionUID与本地响应实体的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就抛出版本不一致的异常(InvalidCastException)。

构造方法

使用字符数组

当使用字符串数组创建的时候,会用的Arrays.copyOf方法和Arrays.copyOfRange方法。将源字符数组数据一一复制到String中的字符数组中。

  //offset为起始位置,count为数量
  public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

字符串构造

使用字符串创建时,会将源String中的valuehash两个属性直接赋值给目标String。

 public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

字节数组构造
char[]字符数组是以unicode码来存储的,Stringchar 为内存形式,byte是网络传输或存储的序列化形式。可以通过charset来解码指定的byte数组,将其解码成unicode的char[]数组,构造String。

String(byte bytes[]) 

String(byte bytes[], int offset, int length)

String(byte bytes[], Charset charset)

String(byte bytes[], String charsetName)

String(byte bytes[], int offset, int length, Charset charset)

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

使用StringbuiderStringBuffer构造
虽然存在当前的构造方式,但是和toString()方法相比,效率比较低。所以可以直接使用toString()代替。

    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());
    }
其他方法 getBytes
String s = "你好,世界!"; 
byte[] bytes = s.getBytes();

这段代码在不同的平台上运行得到结果是不一样的。由于没有指定编码方式,所以在该方法对字符串进行编码的时候就会使用系统的默认编码方式,比如在中文操作系统中可能会使用GBK或者GB2312进行编码,在英文操作系统中有可能使用iso-8859-1进行编码。这样写出来的代码就和机器环境有很强的关联性了,所以,为了避免不必要的麻烦,我们要指定编码方式。如使用以下方式:

比较方法
boolean equals(Object anObject);
boolean contentEquals(StringBuffer sb);
boolean contentEquals(CharSequence cs);
boolean equalsIgnoreCase(String anotherString); //使用toUpperCase方法转换成大写,在进行比较
int compareTo(String anotherString);
int compareToIgnoreCase(String str);
boolean regionMatches(int toffset, String other, int ooffset,int len);  //局部匹配
boolean regionMatches(boolean ignoreCase, int toffset,String other, int ooffset, int len);   //局部匹配
String s = "你好,世界!"; 
byte[] bytes = s.getBytes("utf-8");
其他
ength(); //返回字符串长度

isEmpty(); //返回字符串是否为空

charAt(int index;) //返回字符串中第(index+1)个字符

char[] toCharArray(); //转化成字符数组

trim();// 去掉两端空格

toUpperCase();// 转化为大写

toLowerCase();// 转化为小写

String concat(String str); //拼接字符串

String replace(char oldChar, char newChar); //将字符串中的oldChar字符换成newChar字符

//以上两个方法都使用了String(char[] value, boolean share);

boolean matches(String regex); //判断字符串是否匹配给定的regex正则表达式

boolean contains(CharSequence s); //判断字符串是否包含字符序列s

String[] split(String regex, int limit;) //按照字符regex将字符串分成limit份。

String[] split(String regex);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70401.html

相关文章

  • java.lang.Integer 源码深入解读

    摘要:最近算是比较深入的了解了一下的源码,就想着写点东西记录一下,一来可以加深理解,再来也算是为我刷了那么久平台贡献一点自己的绵薄之力。这两个方法都是给当前的实例的属性赋值,参数为类型的构造器直接将参数赋值给属性,参数为是将方法的返回值赋值。 最近算是比较深入的了解了一下Integer的源码,就想着写点东西记录一下,一来可以加深理解,再来也算是为我刷了那么久segmentfault平台贡献一...

    mingzhong 评论0 收藏0
  • React 源码深度解读(五):首次自定义组件渲染 - Part 2

    摘要:的和真正有效的都各只有一行代码的调用栈如下这中间的函数调用逻辑很清晰,最终会走到这里这里的逻辑很简单,如果不是数组,则调用回调函数如果是数组,则继续调用自身,相当于深度优先遍历。这里的回调函数就是中的这里直接调用,创建。 前言 React 是一个十分庞大的库,由于要同时考虑 ReactDom 和 ReactNative ,还有服务器渲染等,导致其代码抽象化程度很高,嵌套层级非常深,阅读...

    william 评论0 收藏0
  • 关于JustWriting源码的一些解读

    摘要:文件名以在文件系统中的排序返回。将包含完整模式匹配到的文本将包含第一个捕获子组匹配到的文本,以此类推。其实主要是是记录一下自己的笔录,不过还是强烈推荐大家上手,从此写博客就不是什么难事了。 JustWriting是一个用PHP,基于CI框架的极简主义博客系统,在这里,你甚至不需要数据库,直接用Markdown写博客就可以了,就像我此刻一样,直接用Mou来写这篇博客分享一样,So eas...

    booster 评论0 收藏0
  • jQuery源码解读:部份jQuery工具方法实现

    摘要:作为前端最流行的类库,没有之一,源码必须得读一读。本博将不定期更新源码解读内容,如果解读不正确的地方,还请同学们在评论中指正。这里使用的是改变的指向为实例。其实就是中常见的四判断是否是数字函数用于检查其参数是否是无穷大。 jQuery作为前端最流行的类库,没有之一,源码必须得读一读。本博将不定期更新源码解读内容,如果解读不正确的地方,还请同学们在评论中指正。 本系列文章基于jquer...

    Rindia 评论0 收藏0
  • Java IO框架总揽--File源码解读

    摘要:直接继承与,实现了接口和接口,实现接口,意味着对象支持序列化操作,而实现接口,意味着之间可以比较大小。删除此抽象路径名表示的文件或目录。标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。 showImg(https://segmentfault.com/img/bVbi3ls?w=2048&h=164);1 File直接继承与Object,实现了Serializable接口和C...

    rubyshen 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<