所有的類都默認繼承Object這個基類绞铃,基本數(shù)據(jù)類型不是類,所以不繼承喝检,但它們的封裝類繼承嗅辣,使用基本數(shù)據(jù)類型時會自動封箱為封裝類。equals()挠说、getClass()澡谭、hashCode()、toString()是Object常用的方法损俭。
equals(Object obj)方法
API蛙奖,源碼:
public boolean equals(Object obj) {
return (this == obj);
}
==
用于判斷兩個引用是否指向同一個對象。所以equals方法用于判斷兩個對象是否在意義上相等杆兵,即這兩個對象是否是同一個對象雁仲。
Dog d = new Dog();
Cat c = new Cat();
Cat c2 = new Cat();
Dog d2 = d;
System.out.println(d.equals(c));
System.out.println(c.equals(c2));
System.out.println(d.equals(d2));
false //因為兩個實例對象不同
false //因為引用對象c和c2指向不同實例
true //因為引用對象d和d2指向同一實例
String重寫了equals方法,比較兩個String對象是否帶有相同的字節(jié)組合:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof 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;
}
輸出結(jié)果為“true”:
String s = "hello";
String s2 = "hello";
String s3 = new String("world");
String s4 = new String("world");
if (s.equals(s2) && s3.equals(s4)) {
System.out.println("true");
} else {
System.out.println("false");
}
在重寫equals()方法的同時,需要重寫hashCode()方法礼饱,equals()與hashCode()關(guān)系:如果兩個對象equal继蜡,hashCode值相同。
==
用來比較兩個primitive主數(shù)據(jù)類型是否相等吹艇,或者判斷兩個引用是否引用同一個對象。
int a = 1;
int a1 = 2;
a == a1; //false
Dog d = new Dog();
Dog d2 = new Dog();
Cat c = new Cat();
d == c; //false
d == d2; //false
getClass()方法
API昂拂,源碼:
public final native Class<?> getClass();//類型
getClass()返回的對象受神,代表當前對象運行時的類。此對象包含當前對象的類相關(guān)信息格侯,如類名鼻听、包名财著、繼承那些接口、有那些屬性撑碴、有那些方法等撑教。
native方法像一個接口,有實現(xiàn)灰羽,但實現(xiàn)是其他編程語言(如:C)編寫的驮履。abstract關(guān)鍵字代表沒有實現(xiàn),所以不能和native連用廉嚼。
ArrayList<Integer> li = new ArrayList<>();
ArrayList<Float> lf = new ArrayList<>();
System.out.println(li.getClass());
System.out.println(lf.getClass());
if (li.getClass() == lf.getClass()) {
System.out.println("Equals");
} else {
System.out.println("Not Equals");
}
System.out.println(lf.getClass().getName());
System.out.println(lf.getClass().toString());
System.out.println(lf.getClass().getPackage());
System.out.println(Arrays.toString(lf.getClass().getInterfaces()));
class java.util.ArrayList
class java.util.ArrayList
Equals
java.util.ArrayList
class java.util.ArrayList
package java.util, Java Platform API Specification, version 1.8
[interface java.util.List, interface java.util.RandomAccess, interface java.lang.Cloneable, interface java.io.Serializable]
getClass()告訴我們對象從哪里被初始化玫镐,li.getClass()
和lf.getClass()
均為class java.util.ArrayList
,兩個對象均在ArrayList中初始化怠噪。
我們經(jīng)常在反射中使用getClass()方法恐似。
private void reflectData(Object o){
Class objectCla = o.getClass();
//獲取當前對象已聲明的所有屬性(字段Field)
Field[] fs = objectCla.getDeclaredFields();
//獲取當前對象所有的方法
Method[] methods = objectCla.getMethods();
}
hashCode()方法
API,源碼:
public native int hashCode();
此方法返回一個對象的哈希代碼(int類型)傍念,相當于對象的一個唯一ID矫夷。
hashCode()方法和equals()方法的關(guān)系:如果兩個對象"equal",則hashCode相等憋槐;如果兩個對象hashCode值相等双藕,但不一定是同一個對象。String重寫了hashCode方法:
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];//val[i]阳仔,當前字符對應的ASCII值忧陪。h->104
}
hash = h;//緩存hash,提高性能
}
return h;
}
s近范、s2嘶摊、s3都有相同的字符組合,所以三者的hashCode相等评矩,都為99162322叶堆。
String s = "hello";
String s2 = new String("hello");
String s3 = new String("hello");
System.out.println(s.hashCode());//99162322
System.out.println(s2.hashCode());//99162322
System.out.println(s3.hashCode());//99162322
hashCode()主要在Hash集合中起作用,如HashSet斥杜、HashMap等虱颗。HashMap中的作用:往HashMap中put鍵值對元素時,當根據(jù)key的hashCode生成的數(shù)組下標的位置沒有元素時蔗喂,將鍵值對放在此位置上枕。如果有元素,依次判斷此位置鏈表的key的hash值(根據(jù)hashCode生成)是否相同以及(&&)key是否相等弱恒,滿足則替換value,不滿足棋恼,則鏈接到鏈表后面返弹。詳情:HashMap的put方法源碼(jdk1.8)
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
toString()方法
API锈玉,源碼:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
我們從源碼可以看出此方法返回對象運行時類的名稱和一個16進制的哈希碼。常用于將Object對象轉(zhuǎn)換為String义起。
HashMap<String, Object> map = new HashMap<>();
map.put("Integer", 1);//int自動裝箱為Integer
map.put("Float", 1.5f);//float自動裝箱為Float
Integer i = Integer.valueOf(map.get("Integer").toString());
Float f = Float.valueOf(map.get("Float").toString());
我們常使用的toString方法重寫了此方法拉背。如AbstractMap的toString,HashMap繼承此方法默终。
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(',').append(' ');
}
}
StringBuffer的toString:
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}