漫画: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底层原理的朋友,对这个概念一定不会陌生。

 

评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值