4

String、StringBuffer、StringBuilder

 1 year ago
source link: https://blog.51cto.com/u_16188762/6857009
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

String、StringBuffer、StringBuilder

精选 原创

String类

String对象用于保存字符串,是一组字符序列

字符串常量对象是用""括起的字符序列,例如"hello","hi"等

字符串的字符使用Unicode字符编码

(无论是汉字还是字母,一个字符占2个字节)

String常用的构造方法

String s1 = new String();
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
String s5 = new String(byte[] b);

String的继承关系

String、StringBuffer、StringBuilder_String

1)String类是final类,不可以被其他类继承,且代表不可变的字符序列

字符串是不可变的,一个字符串对象一旦被分配,其内容是不可变的

String、StringBuffer、StringBuilder_String_02

2)String类的属性private final char value[]; 是用于存放字符串的本质

【value是一个final类型,不可修改value中存储的地址,但是可以修改地址中存储的内容】

final char[] value = {'w','e','l','l','o'};
value[0] = 'h';
System.out.println(Arrays.toString(value));
//[h, e, l, l, o]

两种创建String对象的区别

方式一:
String s1 = new String("abcde");
方式二:
String s2 = "abcde";
String、StringBuffer、StringBuilder_StringBuilder_03

方式一,先在堆区创建空间,里面有private final char[] value;value先查看常量池中是否有该字符串的数据空间,若有,直接指向,若没有则在常量池中重新创建,然后指向

方式二,在创建时,先看常量池中是否有该字符串的数据空间,若有,直接指向,若没有则在常量池中重新创建,然后指向

字符串的辨析

辨析(1)
String h = "hello" + "hi";

注意: 他只会创建一个对象
编译器会自动做一个优化   String h = "hello" + "hi" = "hellohi";
然后判断常量池的对象,是否有hellohi,没有则创建该对象

辨析(2)
String a = "hello";
String b = "hi";
String c = a + b;

注意:
a中的字符串对象在常量池中
b中的字符串对象在常量池中
c则在堆区中,间接指向a+b结果的字符串
String、StringBuffer、StringBuilder_String_04
其底层原理:
String a = "hello";  // 创建a对象
String b = "hi";  // 创建b对象
先创建一个StringBuilder sb = StringBuilder();
执行sb.append("hello");
执行sb.append("hi");
String c = sb.toString();
最后c指向堆中独对象(String) value[] -> 池中 "hellohi"
String c = a + b;
//练习一
String a = "abc";
String b = new String("abc");
System.out.println(a.equals(b));
System.out.println(a == b);
System.out.println(a == b.intern());
System.out.println(b == b.intern());

//当调用intern方法时,如果常量池已经包含一个等于此对象的字符串,
//则返回池中的字符串,否则将String对象添加到常量池中,并返回此对象的引用
//字符串对象.intern()方法,最终返回的是常量池的地址(对象)

//true
//false
//true
//false
//练习二
public class Test{
	String text = new String("AAA");
  final char[] ch = {'j','a','v','a'};
  public void change(String text, char ch[]){
  	text = "java";
    ch[0] = 'h';
  }
  public static void main(String[] args){
   	Test obj = new Test();
    obj.change(obj.text,obj.ch);
    System.out.print(obj.text + "and");
    System.out.print(obj.ch);
  }
}

//输出结果为: AAAandhava
//练习二的分析如图:
String、StringBuffer、StringBuilder_StringBuffer_05

String类常用方法

//方法比较多,不要可以死记硬背,用多了,自然就熟练了,能达到熟练使用即可

equals
//区分大小写,判断内容是否相等
equalsIgnoreCase
//忽略大小写的判断内容是否相等
length
//获取字符的个数,字符串的长度
indexOf
//获取字符在字符串中第1次出现的索引,索引从0开始,否则,返回-1
lastIndexOf
//获取字符在字符串中最后1次出现的索引,索引从0开始,否则,返回-1
substring
//截取指定范围的子串
trim
//去前后空格
charAt
//获取某索引处的字符,注意不能使用Str[index]这种方式.
toUpperCase
//变大写字母
toLowerCase
//变小写字母
concat
//字符串连接
replace
//替换字符串中的字符(所有都替换)
split
//分割字符串,对于某些分割字符,我们需要转义比如|等
comparetTo 
//比较两个字符串的大小
toCharArray 
//转换成字符数组
format 
//格式字符串, %s字符串 %c字符 %d整型 %.2f浮点型 与C语言类似

StringBuffer类

java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删

StringBuffer常用的构造方法

StringBuffer s1 = new StringBuffer();
 //构造一个不带字符的字符串缓冲区,初始容量默认为16个字符
StringBuffer s2 = new StringBuffer(20);
//构造一个不带字符的字符串缓冲区,初始容量默认为传入参数,初始容量为20
StringBuffer s3 = new StringBuffer("abc");
//构造一个字符串缓冲区,并将内容初始化为指定的字符串内容
//初始容量为 Str.length()+16    3+16 = 19 初始容量为 19

StringBuffer的继承关系

String、StringBuffer、StringBuilder_String_06

1)StringBuffer是一个final类,不能被继承

2)StringBuffer的直接父类是AbstractStringBuilder

3)StringBuffer实现了Serializable,即StringBuffer的对象可以串行化

可串行化(Serializability属性保证的是多个事务并发时的执行顺序要对数据的一致性没有影响。

StringBuffer与String之间的区别

1)在父类中AbstractStringBuilder 有属性char[] value,与String不同,

不是final修饰,该value数组存放字符串内容,引用存放在堆中

2)因为StringBuffer字符内容是存在char[] value,一直在变化数组长度,不用变换地址(每次不用重新创建新对象,然后更换新对象地址)

StringBuffer与String之间的相互转换

//String -> StringBuffer

String str = "hello hi";
//方式一、使用构造器
StringBuffer stringBuffer = new StringBuffer(str);
//方式二、使用append方法
StringBuffer stringBuffer1 = new StringBuffer();
stringBuffer1.append(str);

//StringBuffer -> String
StringBuffer stringBuffer3 = new StringBuffer("goodbye");
//方式一、使用StringBuffer提供的toString方法
String s = stringBuffer3.toString();
//方式二、使用构造器
String s1 = new String(stringBuffer3);

StringBuffer细节辨析

辨析(1)
String str = null;
StringBuffer s1 = new StringBuffer();
s1.append(str);
System.out.println(s1); // null

辨析(2)
StringBuffer s2 = new StringBuffer(str); // 报错
System.out.println(s2);

//why? --- > 看底层源码
//辨析(1)
//先看append方法,super.append(str),str为null,进入appendNull方法中
//	得到结果	返回null
@Override
    @IntrinsicCandidate
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

    public AbstractStringBuilder append(String str) {
            if (str == null) {
                return appendNull();
            }
            int len = str.length();
            ensureCapacityInternal(count + len);
            putStringAt(count, str);
            count += len;
            return this;
     }

	private AbstractStringBuilder appendNull() {
        ensureCapacityInternal(count + 4);
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            val[count++] = 'n';
            val[count++] = 'u';
            val[count++] = 'l';
            val[count++] = 'l';
        } else {
            count = StringUTF16.putCharsAt(val, count,
                                       'n','u', 'l', 'l');
        }
        this.count = count;
        return this;
    }


//辨析(2)
//先看StringBuffer构造方法,到其父类
//发现 int length = str.length(); str 为 null  --- > 空指针异常
//导致结果报错
	@IntrinsicCandidate
    public StringBuffer(String str) {
        super(str);
    }

	AbstractStringBuilder(String str) {
        int length = str.length();
        int capacity = (length < Integer.MAX_VALUE - 16)
                ? length + 16 : Integer.MAX_VALUE;
        final byte initCoder = str.coder();
        coder = initCoder;
        value = (initCoder == LATIN1)
                ? new byte[capacity] : 
        				StringUTF16.newBytesFor(capacity);
        append(str);
    }

StringBuffer类常用方法

append()
//在字符串末尾追加
delete(start,end)	
//删除
replace(start,end,string)
//将start-end之间的内容替换掉,不含end
indexOf()
//查找子串在字符串第一次出现的索引,若找不到返回-1
insert()
//插入
length()
//获取字符串长度

StringBuilder类

一个可变的字符序列,此类提供一个与StringBuffer兼容的API,但不能保证同步(StringBuilder不是线程安全)

StringBuilder类被设计用作StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候。其效率十分高

StringBuilder的继承关系

String、StringBuffer、StringBuilder_StringBuffer_07

1)StringBuilder继承AbstractStringBuilder类

2)实现了Serializable,说明StringBuilder对象时可以串行化的

(对象可以网络传输,可以保存到文件)

3)StringBuilder是final类,不能被继承

4)StringBuilder对象字符序列仍然是存放在其父类AbstractStringBuilder的char[] value 因此字符序列是在堆中

5)StringBuilder的方法,没有做互斥处理,即没有synchronized关键字,因此单线程的情况下使用StringBuilder

StringBuilder常用方法

append()
//在字符串末尾追加
delete(start,end)	
//删除
replace(start,end,string)
//将start-end之间的内容替换掉,不含end
indexOf()
//查找子串在字符串第一次出现的索引,若找不到返回-1
insert()
//插入
length()
//获取字符串长度

String、StringBuffer、StringBuilder选择

1)如果字符串存在大量的修改操作,一般使用StringBuffer、StringBuilder

2)如果字符串存在大量的修改操作,且在单线程的情况下StringBuilder

3)如果字符串存在大量的修改操作,且在多线程的情况下StringBuffer

4)如果字符串存在少量的修改操作,被多个对象引用,使用String

  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK