好久没写代码,也不知为何,上一趟csdn,难的看不懂,简单的不屑看,眼高手低说的就是我了。。
也不知道从什么地方提高自己,对我来说,什么东西似乎都能说上一点,但是再往后,知识储备就不足了,再继续写下去也怕误人子弟。也许有生之年,我能补完自己之前埋下的坑呢?。。
这次准备长期写下去的就是源码解读,有一说一,我不喜欢像某些csdn的5年,10年的账号一样,一天到晚发一些基础知识,啃老本,我甚至怀疑到底是这些人是真的水平太低,还是这些初级Java都会的基础知识太难学??
这一篇在写的时候也是感觉很水很low,但是看源码对于初级Java来说确实进步很大。(其实我就是懒,想水。)
闲话不多说,这一次我准备解读源码,从jdk开始,再到ssm框架,有生之年也许能写完?TAT
先说一下源码解读的流程。
一、下载JDK
我相信大家都下载了jdk环境,而在jdk安装路径下就有jdk的源码文件
如果是使用eclipse的童鞋,点开class文件之后点击弹出的按钮,选择src.zip文件即可。
如果用idea就简单很多,我使用的就是idea。
二、Object
既然是由浅入深,我们就从万物起源----->object类开始说起。
这个类是所有类的父类,在Java代码层面上,他本身并没有太多的问题可说,但是经常会有初级Java面试问equals方法和==的区别。
equals()方法从哪里来呢?自然就是Object类来的。
我们来看下equals()方法的源码:
//Object类的equals()方法
public boolean equals(Object obj) {
return (this == obj);
}
现在,真相已经出来了,equals方法和==号是完全等价的。
但是面试的答案可不是这么回答的,所以我一向很讨厌死记硬背,也完全没有必要死记硬背。
经常会有人说:equals方法比较的是值,而==比较的是地址。
现在看来这种说法并不对,对于Object类来说,equals方法和==号是完全等价的
也就是说只要我们不重写equals方法,那么,==和equals是不分家的。真要说有什么不一样的话,那就是equals方法被空对象调用时会发生空指针异常,而==不会。
三、String.class
那么上面的说法是从哪里来的?
其实罪魁祸首就是他:
String.class
让我们看下String类的equals方法:
//首先咱们得清楚,1.8版本String类的底层实际上就是一个字符数组(在更新的JDK中实用字节数组优化了)
private final char value[];
public boolean equals(Object anObject) {
//即便是String类,第一步也是地址是否相等。
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
//如果传入的比较对象是String或者子类,则强制转换
String anotherString = (String)anObject;
int n = value.length;
//如果长度相同则循环比较各个字符是否相等。
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
由此可见,对于仅有重写了equals方法时才会比较不同,否则equals方法和==是完全相等的。
四、拓展,String对象做比较。
大家都知道,两个new出来的对象肯定不相等(这里指==号做比较)
//此处两个字符串都是new出来的,因此==比较的结果是false,但是由于内容相同,所以equals方法比较的结果是true。
String a = new String("helloworld");
String b = new String("helloworld");
但是字符串就比较恶心了,因为字符串可以不需要new出来。。。
String a = "helloworld";
String b = new String("helloworld");
上面的a和b用==比较的结果肯定是不相等的,但是这是为什么呢?
首先看下String的构造方法
public String(String original) {
//value便是存储字符串的字符数组。
this.value = original.value;
this.hash = original.hash;
}
字符串a,b和他们对应的value数组的关系大概就是如下了:
如果比较的是a.value == b.value 的话,返回结果一定为true,但是
a,b并不是同一个人啊,就像你爸的儿子是你,你妈的儿子也是你,但是你爸!=你妈
五、探究字符串a去了哪里?
对于字符串a
String a = "helloworld";
这个a到底去了哪里?
事实上,jvm虚拟机对于这些在代码中的常量,会直接在类加载的时候加载到常量池(如果重复的话则直接把已经在常量池存在的常量的引用返回),因此字符串a是直接指向常量池的"helloworld";
而new出来的字符串b,则是放在堆上,一个在常量池,一个在堆,它们之间的地址引用做比较自然不会相等~
但是如果是直接传引用的话,最后两个变量的引用都是指向一个对象,那么就是相等的。
String a = "helloworld";
String b = "helloworld";
a==b?//结果为true,创建a时,helloworld直接进常量池,创建b时,常量池已经存在helloworld,将常量池helloworld的引用返回给b
String a = new String("helloworld");
String b = "helloworld";
a==b?//结果为false。
//创建a时,在常量池创建helloworld,接着再用常量池的helloworld为模板,在堆上创建新变量helloworld,然后将堆上的helloworld的引用给a。
//创建b时,拿到常量池的helloworld的引用即可。
//a指向的是堆,b指向的是常量池,永远不可能相等。
String a = "helloworld";
String b = a;
a==b?//结果为true,任何直接传递引用的方式传值,都会导致两个变量指向同一个对象。