学习Java ,很重要的一点就是要学会看Java源码, rt.jar 包就是 运行时库的jar 包,这里里面包含了基本的类库的源代码, jre 使我们的机器能运行Java程序, 而jdk 则是编译Java代码。看源码对我们理解Java的一些原理有很大的帮助,源码就是 jdk1.6/src.zip, 用eclipse 关联它(window->preference->java->installed jre ->jdk1.6 ->选择右侧的编辑->rt.jar->source attachment
->选中你的 jdk1.6/src.zip所在的位置即可) 我们就可以在eclipse中打开了 源码了。
现在进入正题,先看String的源码是怎么写的
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
这里value 源码定义为private final char[] value; 所以当我们创建一个String对象的时候 其实就相当于把值赋给了char [] ,所以String的值和长度是不可变更的 。
这里我们再看看一个很经典的面试问题: String s= new String("xyz"); 这个语句 到底创建了几个对象? 这个问题值得深思 我浏览了一些文章 分析如下:
“xyz”是一个String对象 JVM 首先会在String 池 中搜寻"xyz"对象 如果没有就在String池中 创建一个“xyz”对象,然后遇到new 运算符 在内存中(jvm堆中)构造一个String类对象 ,最好把对象的地址赋给对象引用s。所以这里总共创建了两个对象。第一个是在String池中创建,第二个是在内存中创建。(这里还需注意一点 jvm中 对象储存在堆内存中 变量储存在栈内存中)
再看看一段代码:
String s = "hello";
String s1 = new String("hello");
String s2 = "hello";
System.out.println(s == s1);
System.out.println(s == s2);
输出 false
true
在java运算符中== 是比较两个变量的地址 ;所以我们可以看出 s和s1所引用的地址不是同一个,而s 和s2是同一个地址,也就是引用了同一个对象。我们这样分析:第一条语句:jvm在String池中用equals()方法搜索“hello”对象 没有该对象,创建“hello”对象,返回该地址给S;第三条语句:由于 String池中已经存在“hello”对象,所以直接返回地址给S2;所以 s跟s2的地址相同 输出true;
而 第二条语句 是在堆内存中穿了一个对象 并把地址返回给s1,所以 s跟S1地址不相同,输出false;
equals()方法,源码贴出:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
这句话的意思是对比两个对象的个数和内容,只要有其中一项不符合 就返回false 否则就返回true 也就是对比两个对象的内容
例子:
String s = "hello";
String s3=new String("hello");
System.out.println(s.equals(s3));
输出
true
compareTo()方法 是比较两个String 对象的
贴源码:
public int compareTo(String anotherString) {
int len1 = count;
int len2 = anotherString.count;
int n = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
if (i == j) {
int k = i;
int lim = n + i;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
} else {
while (n-- != 0) {
char c1 = v1[i++];
char c2 = v2[j++];
if (c1 != c2) {
return c1 - c2;
}
}
}
return len1 - len2;
}
如果两个字符串 例如 s=new String("hello") s2=new String("h") 前面的h相等 也就是c1[0]=c2[0] 然后 执行 len1-len2=4
String s="hello";
String s1="h";
System.out.println(s.compareTo(s1));
输出
4
上面的源码中return c1-c2 就是得到两个unicode码的差值
例如
String s="hello";
String s1="hb";
System.out.println(s.compareTo(s1));
第一个值相等 比较第二个'e'-'b'=3
输出为
3