java中Object類的常用方法總結(jié)

一、clone

  • 淺克?。簞?chuàng)建一個(gè)新對象,新對象的屬性和原來對象完全相同,對于非基本類型屬性,仍指向原有屬性所指向的對象的內(nèi)存地址。
  • 深克?。簞?chuàng)建一個(gè)新對象,屬性中引用的其他對象也會(huì)被克隆,不再指向原有對象地址。
    總之深淺克隆都會(huì)在堆中新分配一塊區(qū)域,區(qū)別在于對象屬性引用的對象是否需要進(jìn)行克?。ㄟf歸性的)。

case:

public class Main {

    public static void main(String[] args) {
        // 創(chuàng)建父親(LiSi),兒子(LiWu),孫子(LiLiu)并關(guān)聯(lián)
        Son father = new Son();
        father.setName("LiSi");
        Son son = new Son();
        son.setName("LiWu");
        Son grandSon = new Son();
        grandSon.setName("LiLiu");
        father.setSon(son);
        son.setSon(grandSon);
        // 調(diào)用clone方法
        Son fatherCopy = null;
        try {
            fatherCopy = (Son) father.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        boolean flag1 = fatherCopy==father;
        boolean flag2 = fatherCopy.getSon() == son;
        boolean flag3 = fatherCopy.getSon().getSon() == grandSon;
        // 比較克隆后的地址

        System.out.println(flag1);// false
        System.out.println(flag2);// true
        System.out.println(flag3);// true
        // 比較Name
        flag1= fatherCopy.getName()==father.getName();
        flag2 = fatherCopy.getSon().getName() == son.getName();
        flag3 = fatherCopy.getSon().getSon().getName() == grandSon.getName();
        System.out.println(flag1);// true
        System.out.println(flag2);// true
        System.out.println(flag3);// true
    }
}

如上,如果對象實(shí)現(xiàn)Cloneable并重寫clone方法不進(jìn)行任何操作時(shí),調(diào)用clone是進(jìn)行的淺克隆。

既然實(shí)現(xiàn)Cloneable接口并重寫clone接口只能進(jìn)行淺克隆。但是如果類的引用類型屬性(以及屬性的引用類型屬性)都進(jìn)行淺克隆,直到?jīng)]有引用類型屬性或者引用類型屬性為null時(shí),整體上就形成了深克隆。既對象的引用類型屬性和屬性的應(yīng)用類型屬性都實(shí)現(xiàn)Coloneable,重寫clone方法并在clone方法中進(jìn)行調(diào)用。

protected Object clone() throws CloneNotSupportedException {
      Son result = (Son) super.clone();
    if (son != null) {
        result.son = (Son) son.clone();
    }
    return result;
}

二、equals and hashCode

equals

equals 方法既然是基類 Object 的方法,我們創(chuàng)建的所有的對象都擁有這個(gè)方法,并有權(quán)利去重寫這個(gè)方法。該方法返回一個(gè) boolean 值,代表比較的兩個(gè)對象是否相同,這里的相同的條件由重寫 equals 方法的類來解決。

String str1 = "abc";
String str2 = "abc";
str1.equals(str2);//true

顯然 String 類一定重寫了 equals 方法否則兩個(gè) String 對象內(nèi)存地址肯定不同。


 public boolean equals(Object anObject) {
   //首先判斷兩個(gè)對象的內(nèi)存地址是否相同
   if (this == anObject) {
       return true;
   }
   // 判斷連個(gè)對象是否屬于同一類型。
   if (anObject instanceof String) {
       String anotherString = (String)anObject;
       int n = value.length;
       //長度相同的情況下逐一比較 char 數(shù)組中的每個(gè)元素是否相同
       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;}
hashCode

hashCode()定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數(shù)。
hashCode()的作用是獲取hash值,也稱為散列碼;它實(shí)際上是返回一個(gè)int整數(shù)。這個(gè)hash值的作用是確定該對象在哈希表中的索引位置。也就是說hash值要在一些數(shù)據(jù)結(jié)構(gòu)中才能顯現(xiàn)作用。hashcode一般用在hashmap、hashset里,判斷要把數(shù)據(jù)放在數(shù)組的什么位置。

下面,我們以HashSet為例,來深入說明hashCode()的作用。

假設(shè),HashSet中已經(jīng)有1000個(gè)元素。當(dāng)插入第1001個(gè)元素時(shí),需要怎么處理?因?yàn)镠ashSet是Set集合,它不允許有重復(fù)元素。 “將第1001個(gè)元素逐個(gè)的和前面1000個(gè)元素進(jìn)行比較”?顯然,這個(gè)效率是相等低下的。散列表很好的解決了這個(gè)問題,它根據(jù)元素的散列碼計(jì)算出元素在散列表中的位置,然后將元素插入該位置即可。對于相同的元素,自然是只保存了一個(gè)。 由此可知,若兩個(gè)對象相等,它們的散列碼一定相等;但反過來不一定。在散列表中,
1、如果兩個(gè)對象相等,那么它們的hashCode()值一定要相同。這里的相等是指,通過equals()比較兩個(gè)對象時(shí)返回true。
2、如果兩個(gè)對象hashCode()相等,它們并不一定相等。

轉(zhuǎn)自:http://www.itdecent.cn/p/cf164837f8ed


三、getClass

getClass方法是獲得Class對象的方法之一

class A{
    public void func(){

    }
}

public class Test {
    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.getClass()); // class A
    }
}
反射學(xué)習(xí)

所謂反射,可以理解為在運(yùn)行時(shí)期獲取對象類型信息的操作。傳統(tǒng)的編程方法要求程序員在編譯階段決定使用的類型,但是在反射的幫助下,編程人員可以動(dòng)態(tài)獲取這些信息,從而編寫更加具有可移植性的代碼。嚴(yán)格地說,反射并非編程語言的特性,因?yàn)樵谌魏我环N語言都可以實(shí)現(xiàn)反射機(jī)制,但是如果編程語言本身支持反射,那么反射的實(shí)現(xiàn)就會(huì)方便很多。

Java反射機(jī)制主要提供了以下功能: 在運(yùn)行時(shí)判斷任意一個(gè)對象所屬的類;在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對象;在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法;在運(yùn)行時(shí)調(diào)用任意一個(gè)對象的方法;生成動(dòng)態(tài)代理。

補(bǔ)充:獲取class對象的三種方式
  • 使用forName()方法:Class<?> clazz = Class.forName(className);
  • 調(diào)用屬性:Class<?> clazz = Person.class;
  • 利用對象調(diào)用Object的getClass方法Person p = new Person(); Class<?> clazz = p.getClass();

四、toString

toString()是Object類的一個(gè)公有方法,而所有類都繼承自O(shè)bject類。所以所有類即使不實(shí)現(xiàn)toString方法,也會(huì)存在從Object類繼承來的toString。

類可以實(shí)現(xiàn)toString方法,在控制臺(tái)中打印一個(gè)對象會(huì)自動(dòng)調(diào)用對象類的toString方法。打印的是對象名 + @換為十六進(jìn)制的對象的哈希值

public class Test {
    public static void main(String[] args){
        Car car1 = new Car("寶馬",300000.00);
        Car car2 = new Car("奔馳",500000.00);

        System.out.println(car1); // Car@4554617c
        System.out.println(car2); // Car@74a14482
    }
}

我們也可以實(shí)現(xiàn)自己從寫toString方法在控制臺(tái)中顯示關(guān)于類的有用信息。

@Override
public String toString() {
    return "Car{" +
            "name='" + name + '\'' +
            ", price=" + price +
            '}';
}
// 再次運(yùn)行上面的Test代碼得
// Car{name='寶馬', price=300000.0}
// Car{name='奔馳', price=500000.0}

八種基本數(shù)據(jù)類型沒有toString()方法,只能使用相應(yīng)的包裝類才能使用toString()。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容