前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >漫画:Object类很大,你忍一下

漫画:Object类很大,你忍一下

作者头像
小灰
发布2022-09-01 16:07:48
3390
发布2022-09-01 16:07:48
举报
文章被收录于专栏:程序员小灰程序员小灰

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

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

想要了解clone方法的小伙伴,可以看看之前所讲解 原型模式

getClass()

getClass方法是干什么的呢?首先,getClass方法用于获取一个对象的运行时类(Class),进而通过返回的Class对象,获取该类的相关信息,比如获取该类的构造方法、该类有哪些方法、该类有哪些成员变量等信息。

代码语言:javascript
复制
// 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的部分源码:

代码语言:javascript
复制
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做了一定适配:

代码语言:javascript
复制
  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()

代码语言:javascript
复制
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方法的:

代码语言:javascript
复制
//比较这个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方法的:

代码语言:javascript
复制
//缓存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底层原理的朋友,对这个概念一定不会陌生。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员小灰 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档