String解析及其方法
阅读原文时间:2023年08月15日阅读:1

String解析及其方法

1.前言

2.什么是字符串(String)

3.字符串(String)的两种创建方式及其区别

4.字符串(String)的方法及其部分原码解析

5.字符串(String)的弊端

String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。

字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享

String类表示字符串,在创建之后不能被更改,可用于检查序列的单个字符,搜索字符串,提取字符串,创建字符串副本并将所有字符串全部转换为大写或小写。

字符串有两种创建方式,分别为直接赋值和构造方法。

字符串在创建之后便不会被更改,对于字符串内容的操作都会新创建一个字符串对象

1.直接复制

以双引号内的数据作为字符串存储的数据

String str="hello world";

2.四种构造方法

1.新建一个空字符串

初始化一个新创建的 String 对象,使其表示一个空字符序列

String str1=new String();
空字符串和null的区别
String str2=new String();
String str3=null;

空字符串和null的值都为空

空字符串表示字符串对象引用的值为空,如上str2的值为空,str1指向字符串的内存空间

null表示引用为空,如上str3的引用为空,str3没有指向任何空间

在实际中作用

对字符串的校验过程中,要考虑字符串值的两种"空",既要考虑字符串引用对象值是否为空,又要考虑引用对象是否为空

2.新建String的字符串

初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本

String str4=new String("hello world");

生成的str4是对应参数字符串的副本,但str4是对应新创建的对象

3.新建字符数组的字符串,输出时会自动将数组拼接成字符串

分配一个新的 String,使其表示字符数组参数中当前包含的字符序列

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

适用场景:用于改变字符串的数据

由于字符串在创建之后不能被修改,而字符串没有相应的改变字符串的方法,但是由获取对应索引的数据和将数据转化为字符数组的形式,通过该构造方法可以将字符串的数据进行修改

4.新建字节数组的字符串,输出时会自动将数组拼接成字符串

通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String

byte[] bytes={97,98,99};
String str6=new String(bytes);

使用场景:用于网络中的数据传输,将字节信息转化为字符串时使用

网络中的数据是字节类型,通过该方法可以将字节信息转化为字符串形式再进行处理

3.两者的区别

1.存储

直接赋值:直接赋值进入栈内存中,会进入堆内存的串池中查看是否有相同地址的数据,没有便创建,有的话便复用

构造方法:每new一次便会在堆内存中开辟一个新的空间,生成新对象,不同对象的地址不同

2.字符串的对比

结果为

== 用于比较地址是否相等,equals用于比较具体的值

1. boolean equals(Object anObject)

给定对象表示的 String 与此 String 相等,则返回 true;否则返回 false

源码解释

 public boolean equals(Object anObject) {
     //比较当前对象(this)与给定对象(anObject)的地址是否相等
        if (this == anObject) {
            return true;
        }
    //判断anObject是否是String的实例
        if (anObject instanceof String) {
        //将anObject强制转化为String
            String anotherString = (String)anObject;
        //获取当前对象对应的字符数据的长度
            int n = value.length;
        //判断n与给定对象对应的字符数组的长度是否相等
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
        //比较字符数组对应位置的数据是否相等
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

2.char charAt(int index)

返回指定索引处的 char 值。索引范围为从 0 到 length() - 1。序列的第一个 char 值位于索引 0 处,第二个位于索引 1 处,依此类推,这类似于数组索引

    public char charAt(int index) {
    //判断index是否在给定的索引范围之内,若不在则抛出字符串角标越界
        if ((index < 0) || (index >= value.length)) {
            throw new StringIndexOutOfBoundsException(index);
        }
    //如果在对应的范围内,则获取对应的字符数组对应缩影的数据
        return value[index];
    }

3.public int length()

返回此字符串的长度

    public int length() {
    //返回对应对象字符数组的长度
        return value.length;
    }

4.public String concat(String str)

将指定字符串连接到此字符串的结尾。

如果参数字符串的长度为 0,则返回此 String 对象。否则,创建一个新的 String 对象,用来表示由此 String 对象表示的字符序列和参数字符串表示的字符序列连接而成的字符序列

 public String concat(String str) {
     //判断str是否为空
        if (str.isEmpty()) {
            return this;
        }
        int len = value.length;
        int otherLen = str.length();
    //复制当前对象的值,并指定长度为len+otherLen
        char buf[] = Arrays.copyOf(value, len + otherLen);
    //将str的值添加到buf之后,getChars()的底层是System的arraycopy()
        str.getChars(buf, len);
        return new String(buf, true);
    }

通常使用"+",和concat()的底层原理是一样

5.public String substring(int beginIndex,int endIndex)

返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex

 public String substring(int beginIndex, int endIndex) {
     //判断给定的起始索引和终止索引是否符合要求
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
    //判断终止索引是否大于起始索引
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
    //判断起始索引和终止索引是否对应于字符串对应的字符数组的起始位置和终止位置,如果是,便返回对应的字符串,否则便返回索引的数据
        return ((beginIndex == 0) && (endIndex == value.length)) ? this: new String(value, beginIndex, subLen);
    }

方法的重载

public String substring(int beginIndex)

返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。

6.public String replace(char oldChar,char newChar)

返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

如果 oldChar 在此 String 对象表示的字符序列中没有出现,则返回对此 String 对象的引用。否则,创建一个新的 String 对象,它所表示的字符序列除了所有的 oldChar 都被替换为 newChar 之外,与此 String 对象表示的字符序列相同

 public String replace(CharSequence target, CharSequence replacement) {
     //运用正则表达式对字符串进行替换
     return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
 }

由于字符串一旦创建后便不能更改,因此在进行字符串的拼接过程中,会不断产生新的对象,对于内存的消耗大,同时,进行字符串的反转,过程复杂,内存的消耗大,因此需要其他的字符串类