String 源码及特性分析,关于String,看这篇就够了~

文章目录

    • String 类的声明:
    • String类中有哪些属性:
    • String长度不可变的好处:
    • String的构造方法:
    • 关于String的 equals()方法:
    • String的 hashcode() 方法
    • String、StringBuilder和StringBuffer的区别:

String类位于 java.lang  包下

String 类的声明:

public final class String
	implements java.io.Serializable, Comparable<String>, CharSequence

通过声明可以看出: String类被final 修饰,不可被继承。

String类中有哪些属性:

 private final char value[];
 
 private int hash; // Default to 0  
 
 private static final long serialVersionUID = -6849794470754667710L;
 
 private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];

可以看到 char[] 也是被final修饰String长度不可变,一旦创建,无法更改,值保存在char value[] 中。

String长度不可变的好处:

1. ==节省空间==,频繁创建新的String会造成空间的浪费,所以将String保存到堆中的字符串池中,当有多个String引用指向同样的String字符串时,实际上是指向的是同一个字符串池中的对象。
2. 以String作为HashMap的key,==String的不可变保证了hash值的不可变==。
3. String不可变,可以==避免线程安全的问题==。
4.  String==作为网络连接的参数,它的不可变性提供了安全性==。

String的构造方法:

String 源码及特性分析,关于String,看这篇就够了~_第1张图片
String的构造方法有很多,这里不再详细解释,String不属于8种基本数据类型。它属于引用类型,默认值为null,但是要注意一点:new String()和new String("")都会返回一个空字符串而不是null,原因如下:

// 无参构造
public String() {
        this.value = "".value;
}
// 有参构造
public String(String original) {  // 如果传入的是 ""
     this.value = original.value; // "".value,同上 无参构造   
     this.hash = original.hash;
}

关于String的 equals()方法:

 public boolean equals(Object anObject) {
 		// 地址相同,返回true
        if (this == anObject) {
            return true;
        }
        // 如果传入的参数是String类型,继续。 否则返回false
        if (anObject instanceof String) {
        	// 先做转换
            String anotherString = (String)anObject;
            // 获取当前字符串的长度
            int n = value.length;
            // 如果长度和传入的字符串长度相等,继续。否则返回false
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                // 循环比较 两个数组 每一位的值 是否相等
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                    	// 如果有不相等的值,返回false
                        return false;
                    i++;
                }
                // 循环结束,如果每一位的值都相等,返回true
                return true;
            }
        }
       // 其他情况,都返回false
        return false;
    }

通过以上代码可以看出,String由于重写了equals()方法,所以比较的不是对象的地址,而是实际的字符串值,如果字符串值相等,则返回true

String的 hashcode() 方法

public int hashCode() {

	//先拿到hash属性的值
    int h = hash;
   
  	//如果值为 0 并且 长度 字符串长度大于0 ,则继续,计算hash。
  	//否则说明已经计算过hash,直接返回
    if (h == 0 && value.length > 0) {
        char val[] = value;
		
        for (int i = 0; i < value.length; i++) {
        	// val[0]*31^(n-1) + val[1]*31^(n-2) + ... + val[n-1]
            h = 31 * h + val[i]; 
        }
        hash = h;
    }
    return h;
}

由之前的类的变量分析可以知道,String类中有一个hash 属性,默认为0,而从上面的hashCode()方法又可以看出, 在第一次调用hashCode()方法时候,会重新计算并赋值。之后再调用hashCode()方法便可以直接取hash字段返回。

String hash的计算方式: 以31为权,每一位为字符的ASCII值进行运算,用自然溢出来等效取模。

String、StringBuilder和StringBuffer的区别:

String: 			不可变长字符串,线程安全。
StringBuilder: 	可变长字符串,线程不安全。效率较高
StringBuffer: 	  	可变长字符串,线程安全,效率较低

这里简单说明他们的区别,后续会专门用一篇文章来进行详细分析。

你可能感兴趣的:(源码系列,-,常用类型)