1. Java中的clone方法
1.1 clone:有些時候需要一個和A完全相同新對象B瘪松,并且此后對B對象的任何改動都不會影響A中的值乏悄,即A與B是兩個獨立的對象氮凝。
Java的所有類都默認繼承java.lang.Object類,在該類中有一個clone()方法返回一個拷貝對象(拷貝對象是一個新對象萝映,而不是引用吴叶,并且該拷貝對象包含一些原來對象的信息)。
1.2 clone方法使用
public class Student implements Cloneable {
private String name;
private int age;
private Professor professor;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", professor="
+ professor + "]";
}
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
Cloneable接口是不包含任何方法的序臂!其實這個接口僅僅是一個標志蚌卤,而且 這個標志也僅僅是針對Object類中clone()方法的,如果clone類沒有實現(xiàn)Cloneable接口奥秆,并調(diào)用了Object的clone()方法(也就是調(diào)用了super.Clone()方法)逊彭,那么Object的clone()方法就會拋出 CloneNotSupportedException異常。
1.3 淺復制
class UnCloneA {
private int i;
public UnCloneA(int ii) {
i = ii;
}
public void doublevalue() {
i *= 2;
}
public String toString() {
return Integer.toString(i);
}
}
class CloneB implements Cloneable {
public int aInt;
public UnCloneA unCA = new UnCloneA(111);
public Object clone()throws CloneNotSupportedException{
return super.clone();
}
}
public class CloneMain {
public static void main(String[] a) {
CloneB b1 = new CloneB();
b1.aInt = 11;
System.out.println("before clone,b1.aInt = " + b1.aInt);
System.out.println("before clone,b1.unCA = " + b1.unCA);
try{
CloneB b2 = (CloneB) b1.clone();
b2.aInt = 22;
b2.unCA.doublevalue();
System.out.println("=================================");
System.out.println("after clone,b1.aInt = " + b1.aInt);
System.out.println("after clone,b1.unCA = " + b1.unCA);
System.out.println("=================================");
System.out.println("after clone,b2.aInt = " + b2.aInt);
System.out.println("after clone,b2.unCA = " + b2.unCA);
}catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
b2.unCA和b1.unCA是僅僅指向同一個對象的不同引用.調(diào)用Object類中clone()方法:先在內(nèi)存中開辟一塊和原始對象一樣的空間构订,然后原樣拷貝原始對象中的內(nèi) 容侮叮。對基本數(shù)據(jù)類型,這樣的操作是沒有問題的悼瘾,但對非基本類型變量囊榜,保存的僅僅是對象的引用,這也導致clone后的非基本類型變量和原始對 象中相應(yīng)的變量指向的是同一個對象亥宿。
1.3 深復制
- UnCloneA類也實現(xiàn)和CloneB類一樣的clone功能(實現(xiàn)Cloneable接口卸勺,重載clone()方法)
- 在CloneB的clone()方法中加入一句o.unCA = (UnCloneA)unCA.clone();
關(guān)于StringBuffer:StringBuffer是一個 final類,沒有重載clone()方法烫扼。如果一個類中包含有StringBuffer類型對象或和 StringBuffer相似類的對象曙求,可以只能實現(xiàn)淺復制,或者在類的clone()方法中加一句o.unCA = new StringBuffer(unCA.toString())。
2. equal和hashCode
- 基本數(shù)據(jù)類型只需要用==比較值得大小即可圆到。
- 對于對象而言怎抛,==用于判斷是不是指向同一個對象,即內(nèi)存地址的比較芽淡。
public boolean equals(Object obj){
return (this==obj);
}
從源碼可以看出,沒有重寫 equals時豆赏,是直接用==判斷的挣菲,所以比較的還是兩個對象的引用是否指向同一個內(nèi)存地址。若想用equals()用來判斷對象的值是否相等,就要重寫equals()掷邦。
- hashCode 這是一個 native 本地方法白胀,其實默認的 hashCode 方法返回的就是對象對應(yīng)的內(nèi)存地址。hashCode()的作用是獲取hash值抚岗,也稱為散列碼或杠;它實際上是返回一個int整數(shù)。這個hash值的作用是確定該對象在哈希表中的索引位置宣蔚。也就是說hash值要在一些數(shù)據(jù)結(jié)構(gòu)中才能顯現(xiàn)作用向抢。hashcode一般用在hashmap、hashset里胚委,判斷要把數(shù)據(jù)放在數(shù)組的什么位置挟鸠。
1. 調(diào)用 equals 返回 true 的兩個對象必須具有相等的哈希碼。
2. 如果兩個對象的 hashCode 返回值相同亩冬,調(diào)用它們 equals 方法不一返回 true艘希。(碰撞:若兩個不同的數(shù)據(jù)經(jīng)過相同哈希函數(shù)運算后,得到相同的結(jié)果硅急,那么這種現(xiàn)象就做碰撞)
3. getClass
反射是在運行狀態(tài)中覆享,對于任意一個類,都能夠知道這個類的所有屬性和方法营袜;對于任意一個對象撒顿,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為java語言的反射機制连茧。在Java中核蘸,每個class都有一個相應(yīng)的Class對象。也就是說啸驯,當我們編寫一個類客扎,編譯完成后,在生成的.class文件中罚斗,就會產(chǎn)生一個Class對象徙鱼,用于表示這個類的類型信息。在Java使用類型類來表示一個類型。所有的類型類都是Class類的實例袱吆。
class B{
public void func(){
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(b.getClass()+" "+B.class);//class B,class B
}
}
getClass() 是一個類的實例所具備的方法厌衙,而class() 方法是一個類的方法。
getClass() 是在運行時才確定的绞绒,而class() 方法是在編譯時就確定了婶希。
4. toString
八種基本數(shù)據(jù)類型沒有toString()方法,只能使用相應(yīng)的包裝類才能使用toString()蓬衡。
getClass().getName() + '@' + Integer.toHexString(hashCode())
Object的toString方法返回的字符串: 對象名+@+轉(zhuǎn)換為十六進制的對象的哈希值喻杈,所以當哈希沖突時,Object.toString()返回的字符串也不可避免地重復了狰晚。