Java - String / StringBuffer / StringBuilder

    String是一个final类,代表不可变的字符序列,不能被继承。字符串是常量,它的值在创建之后不能更改。
    String实现了Serializeble接口:表示字符串是支持可序列化的。
    String实现了Comparable接口:表示字符串可以比较大小(字典序)。

String的不可变性

    1. 当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原来的字符串进行赋值。

	String s1 = "abc";   //字面量
	String s2 = "abc";
	System.out.println(s1 == s2);  //true
	s1 = "hello";
	System.out.println(s1 == s2);  //false
	System.out.println(s1);  //hello
	System.out.println(s2);  //abc

    字符串常量池中是不会存储相同内容的字符串。所以重新赋值前 s1 == s2,指向同一个字符串。由于String是不可变的,所以不能在原来的字符串重新赋值,只能在新的地方重新定义一个字符串。修改后,s2指向的字符串“abc”没修改,s1指向新的字符串“hello”。

    2. 当对现有的字符串进行连接操作时,需要重新指定内存区域赋值,不能修改原来的字符串。

	String s1 = "abc";
	String s2 = "abc";
	s1 += "def";
	System.out.println(s1);  //abcdef
	System.out.println(s2);  //abc

    3. 当调用使用String的replace()方法修改字符或字符串时,需要重新指定内存区域赋值,不能修改原来的字符串。

	String s1 = "abc";
	String s2 = s1.replace('a', 'b');
	System.out.println(s1);  //abc
	System.out.println(s2);  //bbc

String不同实例化的对比

	String s1 = "abc";
	//this.value = "".value;
	String s2 = new String();
	//this.value = original.value;
	String s3 = new String(String original);
	
	String s4 = new String(char value[]);

	String s5 = new String(char value[],int stratIndex,int count);

    Q:String s1 = “abc”; 和 String s2 = new String(“abc”); 的区别?
    A:通过字面量的方式给一个字符串赋值,此时的字符串声明在字符串常量池,可以共享。通过new的方式给一个字符串赋值,此时对象声明在中,对象中存了一个指向字符串常量池的地址。
在这里插入图片描述

	String s1 = "abc";
	String s2 = "abc";
	String s3 = new String("abc");
	String s4 = new String("abc");
	System.out.println(s1 == s2);  //true
	System.out.println(s1 == s3);  //false
	System.out.println(s2 == s4);  //false
	System.out.println(s3 == s4);  //false(两个不同的对象)
	
	Person p1 = new Person("abc",10);
	Person p2 = new Person("abc",10);
	Person p3 = new Person(new String("abc"),10);
	System.out.println(p1 == p2);  //false
	System.out.println(p1 == p3);  //false
	System.out.println(p1.getName() == p2.getName());  //true
	System.out.println(p1.getName() == p3.getName());  //false

    Q:String s = new String(“abc”); 在内存创建了几个对象?
    A:两个。一个在堆,一个在字符串常量池。

String不同拼接方式的对比

	String s1 = "hello";
	String s2 = "world";
	String s3 = "helloworld";
	String s4 = "hello" + "world";
	String s5 = s1 + "world";
	String s6 = "hello" + s2;
	String s7 = s1 + s2;
	String s8 = s5.intern();
		
	System.out.println(s3 == s4);  //ture
	System.out.println(s3 == s5);  //false
	System.out.println(s3 == s6);  //false
	System.out.println(s3 == s7);  //false
	System.out.println(s5 == s6);  //false
	System.out.println(s5 == s7);  //false
	System.out.println(s6 == s7);  //false
	System.out.println(s3 == s8);  //true

    常量常量的拼接结果在字符串常量池,且常量池不会存在相同内容的常量。
    只要其中有一个是变量,结果就是一个在中的对象
    如果拼接结果调用intern()方法,返回值就在常量池中。

String的常用方法

                  |——int length()
                  |——boolean isEmpty()
                  |——char charAt(int index):返回指定索引的字符
                  |——byte[] getBytes()
                  |——boolean equals(Object anObject)
                  |——boolean equalsIgnoreCase(String anotherString):判断内容是否相等,忽略大小写
                  |——int compareTo(String anotherString)
                  |——boolean startsWith(String prefix)
                  |——boolean startsWith(String prefix, int toffset)
                  |——boolean endsWith(String suffix)
                  |——int hashCode()
                  |——int indexOf(String str):返回指定子串在此字符串第一次出现的索引
String——|——int indexOf(String str, int fromIndex)
                  |——int lastIndexOf(int ch)
                  |——int lastIndexOf(int ch, int fromIndex):返回指定子串在此字符串最后一次出现的索引,从指定的索引开始反向搜索
                  |——String substring(int beginIndex)
                  |——String substring(int beginIndex, int endIndex):获取子串(左闭右开)
                  |——String replace(char oldChar, char newChar)
                  |——String replace(CharSequence target, CharSequence replacement)
                  |——boolean matches(String regex)
                  |——boolean contains(CharSequence s)
                  |——String[] split(String regex):根据正则表达式分割字符串
                  |——String toLowerCase():所有字符转换为小写
                  |——String toUpperCase():所有字符转换为大写
                  |——String trim():去除字符串前后空格
                  |——char[] toCharArray()
                  |——String valueOf(int i)

String与基本数据类型之间的转换

    字符串——▷基本数据类型、包装类

String——byte:Byte.parseByte(String s);
String——short:Short.parseShort(String s);
String——int:Integer.parseInt(String s);
String——long:Long.parseLong(String s);
String——float:Float.parseFloat(String s);
String——double:Double.parseDouble(String s);
String——boolean:Boolean.parseBoolean(String s);

    基本数据类型、包装类——▷字符串

String.valueOf(char c);
String.valueOf(int i);
String.valueOf(long l);
String.valueOf(float f);
String.valueOf(double d);
String.valueOf(boolean b);

String与char[]之间的转换

    字符串——▷char[]

public char[] toCharArray();

    char[]——▷字符串

new String(char[] c);
new String(char[] c, int offset, int length);

String与byte[]之间的转换

    字符串——▷byte[]

public byte[] getBytes();
public byte[] getBytes(String charsetName);

    byte[]——▷字符串

new String(byte[] b);
new String(byte[] c, int offset, int length);

StringBuffer | StringBuilder

    Q:String、StringBuffer、StringBuilder三者的效率?
    A:StringBuilder > StringBuffer > String

    Q:String、StringBuffer、StringBuilder三者的异同?
    A:String:不可变字符序列。底层使用byte[] value存储。
           StringBuffer:可变字符序列。线程安全,效率低。底层使用byte[] value存储。
           StringBuilder:可变字符序列。线程不安全,效率高。底层使用byte[] value存储。

    我们以StringBuilder为例,分析一下源码,StringBuffer和StringBuilder区别不大,StringBuffer多了一个synchronized关键字。
    默认情况下,扩容为原来容量的2倍+2,同时将原有数组中的元素复制到新数组。

	public final class StringBuilder extends AbstractStringBuilder
			implements java.io.Serializable, CharSequence{
		...
		public StringBuilder() {
        	super(16);  //创建长度为16的数组
    	}
    	public StringBuilder(int capacity) {
        	super(capacity);
    	}
    	public StringBuilder(String str) {
        	super(str.length() + 16);
        	append(str);
    	}
    	...
    	AbstractStringBuilder(int capacity) {
        	if (COMPACT_STRINGS) {
            	value = new byte[capacity];
            	coder = LATIN1;
        	} else {
            	value = StringUTF16.newBytesFor(capacity);
            	coder = UTF16;
        	}
    	}
	    ...
    	public StringBuilder append(String str) {
        	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 void ensureCapacityInternal(int minimumCapacity) {
        	// overflow-conscious code
        	int oldCapacity = value.length >> coder;
        	if (minimumCapacity - oldCapacity > 0) {  //是否需要扩容
            	value = Arrays.copyOf(value,newCapacity(minimumCapacity) << coder);
        	}
    	}
    	...
    	private int newCapacity(int minCapacity) {
        	// overflow-conscious code
        	int oldCapacity = value.length >> coder;
        	int newCapacity = (oldCapacity << 1) + 2;  //长度变为原来的2倍+2
        	if (newCapacity - minCapacity < 0) {
            	newCapacity = minCapacity;
        	}
        	int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
        	return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity;
    	}

    注意里面有一个方法length(),它返回的是当前字符的总数。而不是底层数组的长度。

	StringBuilder builder = new StringBuilder();
	builder.append("abc");
	System.out.println(builder.length());

运行结果:3

	int count;  //The count is the number of characters used.
    public int length() {
        return count;
    }

StringBuilder的常用方法

                               |——StringBuilder append(xxx):用于字符串拼接,其中提供了很多的append()方法。
                               |——StringBuilder delete(int start, int end):删除指定位置的内容,左闭右开
                               |——StringBuilder replace(int start, int end, String str):把[start,end)的内容替换为str,左闭右开
                               |——StringBuilder insert(int offset, xxx):指定位置插入xxx
                               |——StringBuilder reverse():把当前字符序列倒序
StringBuilder——|——int indexOf(String str)
                               |——String substring(int start, int end)
                               |——int length()
                               |——char charAt(int n)
                               |——void setCharAt(int n, char ch)

如有错误请大家指出了(ง •̀_•́)ง (*•̀ㅂ•́)و

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值