Java String总结

String 为什么不可变?

先看下Java8 String类的源码:

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
}

String类是final的,它的所有成员变量也都是final的。为什么是final的?

  1. 线程安全。同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。
  2. 支持hash映射和缓存。因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性使得 hash 值也不会变,不需要重新计算。
  3. 字符串常量池优化。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。

String、StringBuffer和StringBuilder类

String是不可变类,一旦String对象被创建,这个对象包含的字符串序列就不可改变,直到该对象被销毁。

StringBuffer对象则代表一个字符序列可变的字符串,可通过一系列方法改变字符串,如append(), insert(), remove(), 最后在通过toString()方法将其转换为String对象。

从JDK1.5新增StringBuilder类。它和StringBuffer基本相似。
不同的是,StringBuffer是线程安全的;StringBuilder没有实现线程安全功能,所以性能略高。(因此需要创建一个内容可变的字符串对象,优先考虑StringBuilder)

以上三者,都实现了CharSequence接口,因此CharSequence可以认为是字符串协议接口。
常见操作如下:

public static void main(String[] args) {
        String s = new String("abcdefghijk");
        // 字符串的序列从0开始到length()-1
        System.out.println(s.charAt(5)); // f

        String s1 = new String("abcdefghijk");
        String s2 = new String("abcdefghijklmn");
        String s3 = new String("abcdefghijkabcde");
        // 比较两个字符串的大小。
        // 如果两个字符串的字符序列相等,则返回0;不相等时,从两个字符串第0个字符开始比较,返回第一个不相等的字符差
        // 另一个情况,较长的字符串的前面部分恰巧是较短的字符串,则返回它们的长度差。
        System.out.println(s.compareTo(s1)); // 0
        System.out.println(s2.compareTo(s3)); // 返回'l'-'a'的差
        System.out.println(s1.compareTo(s2)); // 返回长度差

        
        StringBuilder sb = new StringBuilder();
        sb.append("java"); // java
        sb.insert(0, "Hello "); //Hello java
        sb.replace(5, 6, ","); //Hello,java
        sb.delete(5, 6); //Hellojava
        // 反转
        sb.reverse(); //avajolleH
        System.out.println(sb.toString());

        System.out.println(sb.length()); //9
        System.out.println(sb.capacity()); //16

        // 只保留指定长度
        sb.setLength(6);
        System.out.println(sb.toString()); // avajol
    }

区别

  1. 可变性
    String 不可变
    StringBuffer 和 StringBuilder 可变
  2. 线程安全
    String 不可变,因此是线程安全的
    StringBuilder 不是线程安全的
    StringBuffer 是线程安全的,内部使用 synchronized 进行同步

String 类的常用方法有哪些?

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。
new String(“hello”)会创建几个对象?

使用这种方式会创建两个字符串对象(前提是字符串常量池中没有 “hello” 这个字符串对象)。
“hello” 属于字符串字面量,因此编译时期会在字符串常量池中创建一个字符串对象,指向这个 “hello” 字符串字面量;
使用 new 的方式会在堆中创建一个字符串对象。

什么是字符串常量池?

字符串常量池保存着所有字符串字面量,这些字面量在编译时期就确定。字符串常量池位于堆内存中,专门用来存储字符串常量。在创建字符串时,JVM首先会检查字符串常量池,如果该字符串已经存在池中,则返回其引用,如果不存在,则创建此字符串并放入池中,并返回其引用。

获取String字节长度

public int length()返回此字符串的长度。长度等于字符串中 Unicode 代码单元的数量。

需要使用下面的方式获取字节长度:

public static void main(String[] args) throws UnsupportedEncodingException {
	String a = "123abc";
	int num = a.getBytes(StandardCharsets.UTF_8).length;
	System.out.println(num);
	a = "中文";
	num = a.getBytes(StandardCharsets.UTF_8).length;
	System.out.println(num);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值