Java学习(20) -- 源码阅读(String)

一、String以下几个特性决定它是不可变的

1、`String`是`final`类,不可继承。
2、字符数组成员变量`value`使用`final`修饰,也就是常量,常量一大好处就是线程安全,所以`String`不需要考虑线程安全问题。
3、通过反射还是可以修改value常量值的,这时候会发现如果字符串是在常量池里,那么这个常量池字符串将会被修改成其他值。
4、成员变量`value`字符数组必须独有,其他程序(不包括String类和反射)不可操作`value`字符数组

二、String 构造器

/**
*创建空的字符串数组
*/
public String() {
     this.value = "".value;
}

//新创建的字符串是参数字符串的副本。不需要,因为字符串是不可变的。
public String(String original) {
     this.value = original.value;
     this.hash = original.hash;
}
//根据数组创建字符串(方式一)
//传入一个字符数组,将该数组拷贝一份复制给value,其实这样做就是为了保证String不可变性
public String(char value[]) {
    this.value = Arrays.copyOf(value, value.length);
}

//根据数组创建字符串(方式二)
//取得传入字符数组的部分元素,在第一种情况下,就是多了对传入的offset count变量判断是否下标越界
public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

//根据数组创建字符串(方式三)
//bytes:需要转换成字符串的字节数组

//offset:字节数组的第一个字节的下标

//length:需要转换成字符串的字节长度=

//charsetName:编码格式的字符串名称,如:UTF-8

//charset:编码格式java.nio.charset.Charset,如:Charset.forName("UTF-8");

public String(byte bytes[], int offset, int length, Charset charset) {
        if (charset == null)
            throw new NullPointerException("charset");
        checkBounds(bytes, offset, length);
        this.value =  StringCoding.decode(charset, bytes, offset, length);
    }

三、String(StringBuffer buffer)和public String(StringBuilder builder)

public String(StringBuffer buffer) {
        synchronized(buffer) {
            this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
        }
    }
public String(StringBuilder builder) {
        this.value = Arrays.copyOf(builder.getValue(), builder.length());
    }

从源码可知,是复制数组然后赋值

四、String.intern() 这是重点

1、字符串常量池,初始是空的,它是由String类私自维护的。
2、当intern方法调用,如果常量池中存在这个字符串(由equals方法判断相等的),则返回常量池中的字符串,否则将这个字符串添加到常量池中,并返回一个对这个对象的引用。
其实就是存在则返回,否则添加并返回。
由此可见,对于任意两个字符串s和t,s.intern() == t.intern() 是 true,s.equals(t) 也是 true。
3、所有的字符串和字符串值的常数表达式都被插入 ,字符串字面量是在 Java™语言规范的3.10.5. String 字面量中定义的,关于字面

char[] value = {'1','a','2','b'};
String str = "1a2b";//常量池中创建
String s = new String(value);//在堆中创建String对象
String intern = s.intern();//从常量池中获取
System.out.println(str==s);//false
System.out.println(str==intern);//true
System.out.println(s==intern);//false   

五、字符串拼接

 

方式一:
String a = "123"+"456";
//这种方式的拼接在class编译后变成
String a = "123456";

方式二:
public void appen(String a) {
   String a = a + "124";
}
//这种编译后在class中是使用StringBuilder的append()拼接
new StringBuilder().append(a).append("124").toString();


//原理可去查看我的语法糖博客

如有疏漏之处,请各位斧正;

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值