聊聊Java中的Object类

转载请注明来源-作者@loongshawn:http://blog.csdn.net/loongshawn/article/details/77198401,建议读者阅读原文,确保获得完整的信息

1.Object描述

先来看看Object的API说明:

public class Object
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class.

Since:
JDK1.0

See Also:
Class

意思是说,Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

2.Object方法摘要

返回值方法主体说明
protected Objectclone()创建并返回此对象的一个副本。
booleanequals(Object obj)指示其他某个对象是否与此对象“相等”。
protected voidfinalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
ClassgetClass()返回此 Object 的运行时类。
inthashCode()返回该对象的哈希码值。
voidnotify()唤醒在此对象监视器上等待的单个线程。
voidnotifyAll()唤醒在此对象监视器上等待的所有线程。
StringtoString()返回该对象的字符串表示。
voidwait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
voidwait(long timeout)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
voidwait(long timeout, int nanos)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

3.拓展说明

3.1 equals(Object obj)方法

equals比较的是两个对象是否“相等”,即引用是否指向同一个对象,侧重判断对象内容是否相同。“==”号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。

public class ObjectTest {

    private class Pikachu{

        private String name;

        private Pikachu(String name){
            this.name = name;
        }
    }

    public static void main(String[] args){

        Pikachu a = new ObjectTest().new Pikachu("A");
        Pikachu b = new ObjectTest().new Pikachu("A");
        Pikachu m = a;

        String c = "AB";
        String d = "AB";

        String e = new String("AB");
        String f = new String("AB");

        System.out.println("a.equals(b):" + a.equals(b));
        System.out.println("c.equals(d):" + c.equals(d));
        System.out.println("e.equals(d):" + e.equals(d));
        System.out.println("e.equals(f):" + e.equals(f));
        System.out.println("m.equals(a):" + m.equals(a));

        System.out.println("a hashcode:" + a.hashCode());
        System.out.println("b hashcode:" + b.hashCode());
        System.out.println("c hashcode:" + c.hashCode());
        System.out.println("d hashcode:" + d.hashCode());
        System.out.println("e hashcode:" + e.hashCode());

        System.out.println(e==f);
        System.out.println(c==d);
    }
}

输出结果:

a.equals(b):false
c.equals(d):true
e.equals(d):true
e.equals(f):true
m.equals(a):true
a hashcode:1580066828
b hashcode:491044090
c hashcode:2081
d hashcode:2081
e hashcode:2081
false
true

从输出结果可以看出,对于new出来的对象,equals返回肯定是false,但有一个特例就是String,如果对象是new String(“XXX”),则只会比较其值。

    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;
    }

比较对象是否相同时需要温习Java堆、栈和常量池相关知识,后面专门讨论下这块内容。

3.2 toString()方法

API中的解释就是,返回该对象的字符串表示。

    private void toStringTest(){

        Pikachu a = new ObjectTest().new Pikachu("A");
        Pikachu b = new ObjectTest().new Pikachu("A");

        System.out.println(a.toString());
        System.out.println(b.toString());
    }

输出结果形如类名+对象内存地址:

com.loongshawn.ObjectTest$Pikachu@5e2de80c
com.loongshawn.ObjectTest$Pikachu@1d44bcfa

如果本意是想输出这个对象的名字呢,则需要重写toString()方法,如下:

    private class Pikachu{

        private String name;

        private Pikachu(String name){
            this.name = name;
        }

        public String toString(){
            return name;
        }
    }

输出结果如下:

A
A

3.3 hashCode()方法

hashCode() 方法用于返回字符串的哈希码。不是什么内存地址,所以理解不要偏了。以字符串对象为例,其哈希码根据以下公式计算:

s[0]*31^(n-1) + s[1]*31^(n-2) + … + s[n-1]

s[i]为字符,n为字符数组长度

对应源码为:

    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];
            }
            hash = h;
        }
        return h;
    }

hashCode()与equals()需要配合起来用,下面总结几点之间的关系:

  • hashCode值相等,不能肯定的说两个对象equals为true。
  • hashCode值不等,两个对象equals结果为false。
  • 两个对象equals结果true,则其hashCode一定相等。

一个对象在任何时刻,其hashCode值不能变,因此在设计程序重写hashCode时,需要选取一个不变的常量来参与hashCode计算,在《Java编程思想》一书中有一条类似的一段话:

“设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该产生同样的值。如果在讲一个对象用put()添加进HashMap时产生一个hashCdoe值,而用get()取出时却产生了另一个hashCode值,那么就无法获取该对象了。所以如果你的hashCode方法依赖于对象中易变的数据,用户就要当心了,因为此数据发生变化时,hashCode()方法就会生成一个不同的散列码”。

3.4 Integer说明

比较Integer对象

Integer i = 3;
int j = 3;
Integer k = 128;
Integer l = 128;

System.out.println(i==j); // true
System.out.println(k==l); // false

值类型int与引用类型Integer比较时,仅比较值;引用类型Integer与引用类型Integer比较时,比较其内存地址。Integer值范围(-128~127)会在第一次使用时进行初始化,因此这个范围内的对象不会新建,返回已存在的内存地址。具体源码如下:

    // 赋值操作
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    // 对象初始化(-128~127)
    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

4.参考

1、类 Object API
2、Java hashCode() 方法
3、浅谈Java中的hashcode方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值