String详解

String详解:

(1)String不属于基本数据类型,Stirng是一个对象
(2)String类被final修饰,不可以被
(3)String可以通过“+“连接
(4)String类的本质是char[]
(5)String运行时维护常量池

类的定义及主要属性

(1)类的定义:
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
(2)主要属性(GDK1.6):
private final char value[];  //String本质就是Char数组
private final int offset;   //偏移位
private final int count;  //就是Sting的length
private int hash;  //hash码

final简析

简单的理解:
    若变量是基本类型则值不变
    若变量是引用类型则引用不变   
String内部变量是被Final修饰的,对String的改变不能将原来的String改变,只能重新返回一个新的String。这是String与其他普通对象的重要区别。

 通过源码理解"对String的改变不能将原来的String改变,只能重新返回一个新的String"这句话。

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);
}

public static char[] copyOfRange(char[] original, int from, int to) {
    int newLength = to - from;
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    char[] copy = new char[newLength];//创建新的数组对象
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

replace方法我们会误以为会发生值的改变,如下

String str = “123”, str = str.replace('1','a'), 我们会误认为a的值发生改变,查看源码发现其实创建了一个新对象,然后让str指向这个对象。

//源码
public String replace(char oldChar, char newChar) {
    if (oldChar != newChar) {
        int len = value.length;
        int i = -1;
        char[] val = value; /* avoid getfield opcode */

        while (++i < len) {
            if (val[i] == oldChar) {
                break;
            }
        }
        if (i < len) {
            char buf[] = new char[len];
            for (int j = 0; j < i; j++) {
                buf[j] = val[j];
            }
            while (i < len) {
                char c = val[i];
                buf[i] = (c == oldChar) ? newChar : c;
                i++;
            }
            return new String(buf, true);//创建新的对象
        }
    }
    return this;
}

字符串的创建

(1)new创建 String str = new String(“123“);
此方式一定会在堆区创建一个新对象,使用String类的intern()方法可以将其放入常量池。
(ps:java不要求常量一定在编译期才能产生)
(2)直接指定 String str = “123”;
对象创建时先查看常量池,常量池中存在就不创建,不存在时创建新对象并且放入常量池。
(3)使用“+” String str = “12” + “3”;
使用直接指定或者使用纯字符串来创建时,先检查常量池。如果存在则不创建,不存在时创建新对象并且放入常量池。
(4) String str2 = "12";
    String str7 = str2 + "1";
    使用包含变量的表达式来创建时不检查常量池。

字符串的创建例子

public class StringTest {
    public static void main(String[] args) {
        //new创建
        String str1 = new String("123");
        //直接指定
        String str2 = "123";
        System.out.println(str1 == str2);//false
        //使用 "+"
        String str3 = "12" + "3";
        System.out.println(str2 == str3);//true
        //使用包含变量的表达式来创建
        String str4 = new String("12");
        String str5 = str4 + "3";
        System.out.println(str5 == str2);//false
        //使用包含变量的表达式来创建
        String str6 = "12";
        String str7 = "3";
        String str8 = str6 + str7;
        System.out.println(str8 == str2);//false

    }
}

改变Stirng对象

String对象真的是不可变的吗?其实我们可以使用反射机制改变,例子如下:

public class StringReflection {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        String str = "123";
        System.out.println(str); //123

        Field valueFiled = String.class.getDeclaredField("value");
        //访问属性设置
        valueFiled.setAccessible(true);
        char[] oldValue = (char[]) valueFiled.get(str);
        oldValue[0] = 'A';
        System.out.println(str);  //A123
    }
}


转载于:https://my.oschina.net/u/2361475/blog/552466

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值