

————— 第二天 —————







————————————






想要了解clone方法的小伙伴,可以看看之前所講解 原型模式
getClass()
getClass方法是干什么的呢?首先,getClass方法用于獲取一個物件的運行時類(Class),進而通過回傳的Class物件,獲取該類的相關資訊,比如獲取該類的構造方法、該類有哪些方法、該類有哪些成員變數等資訊,


// Java用native方法實作 getClass()
public final native Class<?> getClass();
// Android 特殊的實作方式
private transient Class<?> shadow$_klass_;
public final Class<?> getClass() {
return shadow$_klass_;
}
Java默認的Hotspot虛擬機并沒有開辟單獨的Method Area空間,而是有GC Heap的老生代的Metaspace實作的,而Android采用ART VM,這才造成了這種差異,大黃:這是因為是
finalize()
finalize()方法,是Object的protected方法,在發生GC時觸發該方法,
該方法的大致流程,是當物件變成GC Roots不可達時,GC判斷該物件是否覆寫了finalize()方法,若未覆寫,則直接將其回收;否則,若物件未執行過finalize()方法,將其放入F-Queue佇列,由一低優先級執行緒執行該佇列中物件的finalize()方法,
執行finalize()方法完畢后,GC會再次判斷該物件是否可達,若不可達,則進行回收;否則,物件“復活”,
子類可以override該方法,用于防止物件被回收,亦或是防止物件不被回收,
要防止物件被回收,只需讓該物件與GC ROOTS之間存在可達鏈即可,
我們重點看看FileInputStream、FileOutputStream、Connection等類怎么防止用戶忘記釋放資源吧,如下是FileInputStream的部分原始碼:
protected void finalize() throws IOException {
// Android新增 CloseGuard確保FlieInputStream回收更安全
if (guard != null) {
guard.warnIfOpen();
}
//Java利用 FileDescriptor確保FileInputStream不可達,可以被安全回收
if ((fd != null) && (fd != FileDescriptor.in)) {
close();
}
}
toString()
toString()方法,恐怕是大家最常用的方法了,該方法回傳該物件的String表示,


舉個例子,Integer的toString()方法,就針對Android做了一定適配:
public String toString() {
return toString(this.value);
}
//回傳指定十進制整數的 String
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
// small是 Android特有的變數,用二維Array快取較小(兩位數)數字的 String
boolean negative = i < 0;
boolean small = negative ? i > -100 : i < 100;
if (small) {
final String[] smallValues = negative ?
SMALL_NEG_VALUES : SMALL_NONNEG_VALUES;
if (negative) {
i = -i;
if (smallValues[i] == null) {
smallValues[i] =
i < 10 ?
new String(new char[]{'-', DigitOnes[i]}):
new String(new char[]{'-', DigitTens[i], DigitOnes[i]});
}
} else {
if (smallValues[i] == null) {
smallValues[i] =
i < 10 ?
new String(new char[]{DigitOnes[i]}):
new String(new char[]{DigitTens[i], DigitOnes[i]});
}
}
return smallValues[i];
}
int size = negative ? stringSize(-i) + 1 :
stringSize(i);
// getChars()方法略
char[] buf = new char[size];
getChars(i, size, buf);
return new String(buf);
}
equals() 和 hashcode()

、

public boolean equals(Object obj) {
return (this == obj);
}
想要比較值是否相同,該怎么辦呢?需要重寫equals(),
重寫equals(),要注意以下幾點注意事項:
(1)對任意x,x.equals(x)一定回傳true
(2)對任意x,y,如果x.equals(y)回傳true,則y.equals(x)也一定回傳true
(3)對任意x,y,z,如果x.equals(y)回傳true,y.equals(z)也回傳true,則x.equals(z)也一定回傳true
(4)對任意x,y,如果物件中用于比較的資訊沒有改變,那么無論呼叫多少次x.equals(y),回傳的結果應該保持一致,要么一直回傳true,要么一直回傳false
(5)對任意不是null的x,x.equals(null)一定回傳false


下面,我們先看一下String類是如何實作equals方法的:
//比較這個String和另一個物件,當且僅當那個物件不為null,且與這個String有相同的字符排列順序時回傳true
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = length();
if (n == anotherString.length()) {
int i = 0;
while (n-- != 0) {
if (charAt(i) != anotherString.charAt(i))
return false;
i++;
}
return true;
}
}
return false;
}
接下來,我們再看一下String類是如何實作hashcode方法的:
//快取String的hashcode()
private int hash; // 默認為0
public int hashCode() {
int h = hash;
final int len = length();
if (h == 0 && len > 0) {
for (int i = 0; i < len; i++) {
h = 31 * h + charAt(i);
}
hash = h;
}
return h;
}
如果兩個物件的hashCode回傳值相同,但它們的equals()方法卻有可能最侄訓傳false,這種情況叫做hash碰撞,
熟悉HashMap底層原理的朋友,對這個概念一定不會陌生,


轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/290695.html
標籤:其他
