漫画:Object类很大,你忍一下
Posted 程序员小灰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漫画:Object类很大,你忍一下相关的知识,希望对你有一定的参考价值。
————— 第二天 —————
————————————
想要了解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底层原理的朋友,对这个概念一定不会陌生。
以上是关于漫画:Object类很大,你忍一下的主要内容,如果未能解决你的问题,请参考以下文章