JDK1.6 源码学习笔记

为了进一步的提高自己的技术水平,开始阅读和学习Java源码。
为了能和大家互相学习和交流,今天决定将自己的学习笔记发布到blog上。
一来,作为自己学习的记录;
二来,也希望可以和大家一起交流学习。

本人能力有限,如有错误的地方,请大家批评指正,更希望大家可以帮助我解决一些在学习中的疑难问题(疑难问题会在每节笔记的最后提出来,欢迎大家一起讨论)。


源码学习JDK版本:JDK1.6


第一节:java.lang.String

1.String在内部是以字符数组的形式存放的

private final char value[];

并且通过起始坐标和大小来定义表示的字符串

private final int offset;
private final int count;

2.Strings are constant.

  java中的String是"常量"的形式,在被创建后,是不能被改变的,个人理解成String是一种共享的状态。

String str1 = "abc";
String str2 = "abc";

在内存中,只有一个"abc",str1和str2都是指向这个唯一的"abc"的地址。

这一点有可以通过String的构造方法进一步确认。

public String(String original) {
	int size = original.count;
	char[] originalValue = original.value;
	char[] v;
  	if (originalValue.length > size) {
 	    // The array representing the String is bigger than the new
 	    // String itself.  Perhaps this constructor is being called
 	    // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
 	} else {
 	    // The array representing the String is the same
 	    // size as the String, so no point in making a copy.
	    v = originalValue;
 	}
	this.offset = 0;
	this.count = size;
	this.value = v;
    }
可以从构造方法看出,在新建一个String时,只有当参数中字符串value的长度大于传入的参数长度count时,才会调用Arrays.copyOfRange来新建一个新的String的实例,从而产生一个指向此字符的新地址;否则新String中的字符数组将指向传入的String的字符数组的坐标,两者共享此字符,而不会去新增一个实例。
但是,针对通过char[]形式新建的字符串则不同,系统会copy一份char[]复制给String对象,这一点可以从String的另外一个构造方法看出:
public String(char value[]) {
	this.offset = 0;
	this.count = value.length;
	this.value = StringValue.from(value);
    }
StringValue.from(value)方法将会调用Arrays.copyOf(),从而在新的地址上产生一个新的char[]。

另外,String内部存放的char value[]也是无法直接得到的,这一点可以从String的方法getChars()看出来。getChars()方法,每次都是返回String内部的字符串数组的一个copy,而不是String自己的char[]。
这也可以验证上面说的"String在被创建后,是不能直接被改变的"。
void getChars(char dst[], int dstBegin) {
        System.arraycopy(value, offset, dst, dstBegin, count);
    }

public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > count) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, offset + srcBegin, dst, dstBegin,
             srcEnd - srcBegin);
    }


PS:

Arrays.copyOf()和Arrays.copyOfRange()方法都将会调用底层的System.arraycopy()来复制一份新的数组。


疑问1:

char data[] = {'a', 'b', 'c'};
String str = new String(data); 

如果改变data,str是否也会改变?

个人作答:改变data,不会引起str的改变。因为new String(data)将会使用构造方法public String(char value[]){},而此构造方法将会copy一个新的char[]。


疑问2:

String str1 = "abc";
String str2 = str1;
String str3 = new String(str1);

此处str1、str2、str3按道理,他们的属性char[] value对应的值应该是一样(内存地址引用一样),但是不知道该如何去验证,希望知道的朋友指点一下,谢谢。


本人的第一篇JDK源码阅读的文章到此结束,希望大家指出其中的不足(包括源码解读的错误,也包括blog文章的建议)。

另外,如果大家有兴趣转载,请注明原文出处,谢谢!


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值