String类

文章详细介绍了Java中的String类,包括其不可变性、内存分布、字符串拼接以及常用方法。同时对比了StringBuffer,强调了在频繁字符串操作时使用StringBuffer以提高性能,并解释了其线程安全的特性。
摘要由CSDN通过智能技术生成

String类

概述

​ 在Java中 字符串时最广泛应用的数据,Java提供了String、StringBuffer、StringBuilder类 来创建和操作字符串。并且在Java中,字符串被当作对象来处理,字符串时引用类型

字符串不可修改的原因

  • String 是一个被final修饰的类
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    /**
     * Class String is special cased within the Serialization Stream Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */
    .......
}
  • String 对象的字符内容存储在被 private和final 修饰的 字符数组中,即value[]
  • private 意味着外面无法直接获取字符数组,而String没有提供value的 get 和 set 方法
  • final 一位置字符数组的引用不可改变,即不可通过让 value 指向新的数组对象来实现修改String对象;而String 也没哟提供方法来修改value数组某个元素值,因此字符串的字符数组内容也不可变

字符串修改结果方式

  • 字符串的拼接
  • 字符串的截取
  • 字符串的替换
  • 特点:每次都需要创建一个新的char数组表示修改结果

字符串内存分析

字面量

​ 每一个字面量都是一个String对象

新建字符串对象

​ 使用new创建字符串对象

//常量与新建的对象
public class Demo {
    public static void main(String[] args) {
        String s1 = "Hello word";//字面量
        String s2 = new String("Hello2");
    }
}

字符串存储分析

  • 字符串常量保存在常量池中
    • 编译代码时,编译程序会将所用常量都保存在 方法区中的常量池里。因此,相同常量的所有对象,实际上就是存储与常量池中的同一个对象
    • 常量池中相同的字符串可共享
public class Demo {
    public static void main(String[] args) {
        String s1 = "Hello word";
        String s2 = "Hello word";
        String s3 = "hel";
        System.out.println("字符串常量在常量池,相同值:"+(s1==s2));
        System.out.println("不相同值:"+(s1==s3));
    }
}
//结果
字符串常量在常量池,相同值:true
不相同值:false
  • 使用 new 创建字符串保存在堆中

     String s2 = new String("Hello word");
    
    • 上面的new 代码有两个对象,一个在常量池,一个在堆中。虽然内容相同,但并不是同一个对象
public class Demo {
    public static void main(String[] args) {
        String s1 = "Hello word";
        String s2 = new String("Hello word");
        System.out.println("存储区域不同:"+(s1==s2));
    }
}
//结果
存储区域不同:false

字符串的存储分布图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HgUy1BNb-1678341301021)(G:\Java-栈\常用类\常量与对象内存图.PNG)]

字符串的拼接

public class Demo {
    public static void main(String[] args) {
        String s1 = "Hello";//常量
        String s2 = " word";//常量
        String s3 = s1 + s2;// s3 变量
        String s4 = "Hello"+" word";常量
        String s5 = s1 + " word";// s5 变量
        String s6 = "Hello"+" word";//常量
        String s7 = s1 + s2;// s7 变量
        System.out.println(s3);
        System.out.println(s4);
        System.out.println(s5);
        System.out.println("-----------");
        System.out.println(s3==s4);
        System.out.println(s4==s5);
        System.out.println(s3==s5);
        System.out.println(s4==s6);
        System.out.println(s3==s7);
        System.out.println("-------------");
        String s8 = (s1+s2).intern();//变到常量池
        System.out.println(s8==s4);
    }
}
//结果
Hello word
Hello word
Hello word
-----------
false
false
false
true
false
-------------
true
Process finished with exit code 0

小结1:

  • 常量与常量的拼接结果在常量池
  • 拼接的两者中只要其中有一个是变量,结果就在堆中
  • 拼接的结果调用intern() 方法,就在常量池中

比较字符串

  • String类中重写了equals 方法,使用自付出的内日你哥来比较两个对象
public class Demo2 {
    public static void main(String[] args) {
        String sr1 = "work";
        String sr2 = new String("work");
        System.out.println("比较引用地址:"+(sr1==sr2));
        System.out.println("比较内容:"+sr1.equals(sr2));
    }
}

常用方法

1.创建字符串

public class Demo3 {

    public static void main(String[] args) {
        byte[] buf = {97,98,99};
        String str = new String(buf);//使用一个字节数组构建字符串对象
        String str2 = new String(buf,1,2);//使用一个字节数组的一部分创建字符串对象
        System.out.println(str);
        System.out.println(str2);
        System.out.println("-----------------");
        char[] chars = {'1','6','号','放','假'};
        String string = new String(chars);
        String string1 = new String(chars,0,3);//使用字符数组构建一个字符串
        System.out.println(string);
        System.out.println(string1);
        System.out.println("------------------");
        String string2 = new String("abcde");//使用字符串字面量创建字符串
        System.out.println(string2);
        System.out.println("---------------");
        int[] arr = {98,99,100};
        String string3 = new String(arr,0,3);//使用整型数组创建字符串
        System.out.println(string3);
    }
}
//结果
abc
bc
-----------------
16号放假
16------------------
abcde
---------------
bcd

Process finished with exit code 0

2.length()

  • 获取字符串的长度
public class Demo4 {
    public static void main(String[] args) {
        String s = "abdjdsl";
        System.out.println("长度:"+s.length());//长度方法
    }
}
//结果
长度:7

Process finished with exit code 0

3.字符串转换为字节数组或字符数组

  • public char[] toCharArray()
  • public byte[] getByte()
public class Demo4 {
    public static void main(String[] args) {
        String s = "abdjdsl";
        char[] charArray = s.toCharArray();
        System.out.println("字符数组:\n"+ Arrays.toString(charArray));
        System.out.println("-------------");
        byte[] buf = s.getBytes();
        System.out.println("字节数组:\n"+Arrays.toString(buf));
    }
}
//结果
字符数组:
[a, b, d, j, d, s, l]
-------------
字节数组:
[97, 98, 100, 106, 100, 115, 108]

Process finished with exit code 0

4,大小写转换

  • public String toUpperCase()
  • public String toLowerCase()
public class Demo4 {
    public static void main(String[] args) {
        String s = "abABCl";
        System.out.println("转大写:\n"+s.toUpperCase());
        System.out.println("转小写:\n"+s.toLowerCase());
    }
}
//结果
转大写:
ABABCL
转小写:
ababcl

5.实现字符串的链接

(+)
  • 字符串和热议类型之间使用 ”+“ ,所有基本类型都转为字符串,所有引用类型都会调用toString() ,最后在执行字符串链接
public class Demo4 {
    public static void main(String[] args) {
       int age = 7;
       String s = "He is " + age + " years old";
        System.out.println(s);
    }
}
//结果
He is 7 years old
    
Process finished with exit code 0
public String concat(String str)方法
public class Demo4 {
    public static void main(String[] args) {
       int age = 7;
       String s = "He is ".concat(String.valueOf(age)).concat(" years old.");
       System.out.println(s);
       String s2 = "He is ".concat(age+"").concat(" years old.");
        System.out.println(s2);
    }
其他类型转换为字符串的两种方法
  • String.valueOf(参数类型 参数)
  • “”+参数
  • 参数+“”

6.public String trim()

  • 去掉字符串两端的空格
public class Demo4 {
    public static void main(String[] args) {
       String s = " Hello word ";
       System.out.println("原来:"+s);
       System.out.println("现在:"+s.trim());
    }
}
//结果
原来: Hello word 
现在:Hello word

Process finished with exit code 0

7.判断相关方法

  • 该方法返回值均为 boolean类型
方法声明方法作用
public boolean equals(Object obj)比较字符串内容是否相同,且区分大写
public boolean equalsIgnoranceCase(String art)比较字符串内容是否相同,忽略大小写
public boolean contians(String str)判断字符串是否包含另一个字符串
public boolean startsWith(String str)判断字符串是否以指定字符串开头
public boolean endsWIth(String str)判断字符串是否以指定字符串结尾
public boolean isEmpty()判断字符串是否为空
public class Demo4 {
    public static void main(String[] args) {
       String s = "abc";
       byte[] buf = {97,98,99,100};
       String s2 = new String(buf);
       System.out.println(s2);
       System.out.println("比较字符串内容是否相同 区分大小写:"+s.equals(s2));
       System.out.println("比较字符串内容是否相同 不区分大小写:"+s.equalsIgnoreCase(s2));
        System.out.println("s2是否包含s:"+s2.contains(s));
        System.out.println("s2是否以s开头:"+s2.startsWith(s));
        System.out.println("s2是否以s结尾:"+s2.endsWith(s));
        System.out.println("s2是否为空:"+s2.isEmpty());
    }
}
//结果
abcd
比较字符串内容是否相同 区分大小写:false
比较字符串内容是否相同 不区分大小写:false
s2是否包含s:true
s2是否以s开头:true
s2是否以s结尾:false
s2是否为空:false

Process finished with exit code 

8.字符串的定位

  • 字符串的索引是从0开始
方法声明方法作用
public char charAt(int index)获取执行索引值的字符
public int indexOf(char ch)//返回此字符在字符串中第一次出现的索引值,如果都不匹配则返回-1
public int indexOf(String str)返回指定字符串在字符串中第一次出现的索引值,如果都不匹配则返回-1
public int lastIndexOf(int ch)返回指定字符在字符串中最后一次出现的索引值,如果都不匹配则返回-1
public int lastIndexOf(iString str)返回指定字符串在字符串最后一次出现的索引值,如果都不匹配则返回-1
public class Demo4 {
    public static void main(String[] args) {
        int[] arry = {97, 98, 99, 100, 97, 98, 99, 100};
        String str = new String(arry, 0, 8);
        System.out.println(str);
        char ch = str.charAt(0);
        System.out.println("指定索引值的字符" + ch);
        int count1 = str.indexOf('b');
        System.out.println("字符b第一次出现的位置:" + count1);
        int count2 = str.indexOf("abd");
        System.out.println("字符串abd第一次出现的位置:" + count2);
        int count3 = str.lastIndexOf('d');
        System.out.println("字符b最后第一次出现的位置:" + count3);
        int count4 = str.lastIndexOf("abc");
        System.out.println("字符串abc最后第一次出现的位置:" + count4);

    }
}
//结果
abcdabcd
指定索引值的字符a
字符b第一次出现的位置:1
字符串abd第一次出现的位置:-1
字符b最后第一次出现的位置:7
字符串abc最后第一次出现的位置:4

Process finished with exit code 0

9.替换

方法声明方法作用
public String replace(char old,char new)替换指定的字符
public class Demo4 {
    public static void main(String[] args) {
        char[] chars = {'a','b','c','d','d'};
        String str = new String(chars);
        System.out.println(str);
        String strNew = str.replace('d','1');
        System.out.println("将字符d替换成字符1:"+strNew);
    }
}
//结果
abcdd
将字符d替换成字符1:abc11

Process finished with exit code 

10.获取子串

方法声明方法作用
public String subString(int start)指定位置开始截取字符串,直到末尾 [start,lenght)
public String subString(int start,int end)截取指定范围内的字符串 [start,end)
public class Demo4 {
    public static void main(String[] args) {
        String str = "我是真的是你爹";
        System.out.println(str);
        String st1 = str.substring(2);
        System.out.println("从下标为2开始,到结束:"+st1);
        String st2 = str.substring(4,6);
        System.out.println("从下标为4-6截取:"+st2);
    }
}
//结果
我是真的是你爹
从下标为2开始,到结束:真的是你爹
从下标为4-6截取:是你

Process finished with exit code 0

11.比较字符串

方法声明方法作用
public int compareTo(String str)按字典顺序进行比较,区分大小写 (做减法,调用对象-比较对象)
public int compareToIgnoreCase(String str)按字典顺序进行比较,忽略大小写 (做减法,调用对象-比较对象)
public class Demo4 {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ABCD8";
        int count1 = s1.compareTo(s2);
        System.out.println("s1与s2比较,区分大小写:" + count1);
        int count2 = s1.compareToIgnoreCase(s2);
        System.out.println("s1与s2比较,忽略大小写:" + count2);
    }
}
//结果
s1与s2比较,区分大小写:32
s1与s2比较,忽略大小写:-2

Process finished with exit code 0

12.拆分字符串

方法声明方法
public String[] split(String regex)分割字符串为一个字符串数组。通常使用逗号
public class Demo4 {
    public static void main(String[] args) {
        String str = "2003,2,10";
        System.out.println(str);
        String[] strArray = str.split(",");
        System.out.println(Arrays.toString(strArray));
    }
}
//结果
2003,2,10
[2003, 2, 10]

Process finished with exit code 0

13.将其他数据转换为字符串

方法声明方法作用
public static String valueOf(boolean b)返回boolean 参数的字符串表示形式
public static String valueOf(char c)返回char 参数的字符串表示形式
public static String valueOf(char[] cArray)返回char数组 参数的字符串表示形式
public static String valueOfchar[] cArray,int offset,int count)返回char数组参数的特定子数组的字符串表示形式
public static String valueOf(double d)返回double 参数的字符串表示形式
public static String valueOf(float f)返回float参数的字符串表示形式
public static String valueOf(int i)返回int 参数的字符串表示形式
public static String valueOf(long l)返回long参数的字符串表示形式
public static String valueOf(Object obj)返回Object 参数的字符串表示形式

StringBuffer类

1.理解

  • ​ 为什么需要StringBuffer

由于String的内容是不可变的,在频繁操作字符串的应用中,导致String对象泛滥,不断地被创建和销毁,占用大量的内存和cpu时间

public class Demo4 {
    public static void main(String[] args) {
        Date date = new Date();
        String result = "";
        for (int i = 0; i < 100000; i++) {
            result += "A";
        }
    }
}

这将创建100000个对象,其中-99999个对象是临时对象,是计算的中间结果。JVM 需要花费大量的内存来存放,也需要大量的CPU时间来回收对象。

因此,通过使用可变的字符串缓冲区类(StringBuffer) 来完成类似的 工作:

public class Demo4 {
    public static void main(String[] args) {
        Date date = new Date();
        StringBuffer buffer = new StringBuffer(100*1024);
        for (int i = 0; i < 100000; i++) {
            buffer.append("A");
        }
        String result = buffer.toString();
    }
}

2.缓冲原理

  • StringBuffer 对象内部有一个缓冲区,默认缓冲区的容量是 16字节
  • 通过String Buffer de append()方法 向缓冲区中不断追加数据,当数据的大小超过缓冲区的大小时,系统会重新创建一个原来缓冲区的一倍大的新缓冲区,并将原缓冲区中的数据拷贝到新缓冲区中,这个操作非常好资源。
  • 因此,需要预估数据所占空间大小,在创建缓冲区时 与分配最大值,防止重新创建缓冲区,提高系统性能
1.拼接字符串
  • ​ 第一种方法
public class Demo4 {
    public static void main(String[] args) {
        String st1 = "Hello";
        String st2 = "word";
        String st3 = "Yunnan";
        String st4 = st1 + st2;
        String st5 = st4 + st3;//有临时变量st4
        System.out.println(st5);
    }
}
  • ​ 第二种
public class Demo4 {
    public static void main(String[] args) {
        String st1 = "Hello";
        String st2 = "word";
        String st3 = "Yunnan";
        StringBuffer buffer = new StringBuffer(1024);//缓冲区初始值大小
        buffer.append(st1).append(st2).append(st3);
        String st4 = buffer.toString();//toString()获得字符串
        System.out.println(st4);
    }
}

这个方法只需要创建一个StringBuffer 对象,不需要额外创建对象,最后直接缓冲区中的值为一个字符串。

HellowordYunnan1024
  • 特点:一次性分配缓冲 之后不需要再创建额外的临时变量,整个性能会非常高

3.常用方式

  • 创建一个StringBuffer对象
  • 使用append 增加数据
xxxxxxxxxx public class Demo4 {    public static void main(String[] args) {        String st1 = "Hello";        String st2 = "word";        String st3 = "Yunnan";        StringBuffer buffer = new StringBuffer(1024);//缓冲区初始值大小        buffer.append(st1).append(st2).append(st3);        String st4 = buffer.toString();//toString()获得字符串        System.out.println(st4);    }}

4.方法

1.添加

方法声明方法作用
StingBuffer()无参构造器
StringBuffer(int capacity)指定容量的字符串缓冲类(缓冲区域空间大小) 构造器
StringBuffer(String str)指定字符串内容缓冲对象
StringBuffer append(xxx)在缓冲区的尾部添加新的文本对象,它支持任意类型,都自动被转换为字符串
StringBuffer insert(int offset,xxx)在指定的索引位置添加新的文本对象

2.查看

方法声明方法作用
int capacity()返回当前容量
int length()返回长度(字符数)
int indexOf(String str)返回第一次出现的指定字符串在该字符串中的索引
String subString(int strat)从指定位置截取到末尾
String subString(int start,int end)截取start 到 end的字符串,[start,end)
String toString()返回StringBuffer 中的字符串

3.修改

方法声明方法作用
StringBuffer replace(int start,int end,String str)指定字符串替换子串,[start,end)
setCharAt(int index,char ch)替换指定位置中的字符

4.删除

方法声明方法作用
StringBuffer deleteChar(int index)删除指定的位置的字符,并返回本身
StringBuffer delete(int start,int end)删除从从指定位置开始,指定位置结束的内容,[strat,end)

5.反序

方法声明方法作用
StringBuffer reserve()字符串反转

区别

String StringBuffer和StringBuilder

StringStringBufferStringBuilder
JDK版本JDK1.0JDK1.0JDK1.5
线程安全
效率
值可变性

偏移量

  • 偏移量的意思是前面几个不要
  • 单词:offset
  • 例:偏移量=2,前面2个不要 从第三个开始

自动扩容的方式

ex) | 删除指定的位置的字符,并返回本身 |
| StringBuffer delete(int start,int end) | 删除从从指定位置开始,指定位置结束的内容,[strat,end) |

5.反序

方法声明方法作用
StringBuffer reserve()字符串反转

区别

String StringBuffer和StringBuilder

StringStringBufferStringBuilder
JDK版本JDK1.0JDK1.0JDK1.5
线程安全
效率
值可变性

偏移量

  • 偏移量的意思是前面几个不要
  • 单词:offset
  • 例:偏移量=2,前面2个不要 从第三个开始
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼不咸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值