聊聊Java中的Object类

来源:互联网 发布:淘宝上可以买彩票吗 编辑:程序博客网 时间:2024/05/21 11:28

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

1.Object描述

先来看看Object的API说明:

public class ObjectClass 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.0See Also:Class

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

2.Object方法摘要

返回值 方法主体 说明 protected Object clone() 创建并返回此对象的一个副本。 boolean equals(Object obj) 指示其他某个对象是否与此对象“相等”。 protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 Class getClass() 返回此 Object 的运行时类。 int hashCode() 返回该对象的哈希码值。 void notify() 唤醒在此对象监视器上等待的单个线程。 void notifyAll() 唤醒在此对象监视器上等待的所有线程。 String toString() 返回该对象的字符串表示。 void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 void wait(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):falsec.equals(d):truee.equals(d):truee.equals(f):truem.equals(a):truea hashcode:1580066828b hashcode:491044090c hashcode:2081d hashcode:2081e hashcode:2081falsetrue

从输出结果可以看出,对于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@5e2de80ccom.loongshawn.ObjectTest$Pikachu@1d44bcfa

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

    private class Pikachu{        private String name;        private Pikachu(String name){            this.name = name;        }        public String toString(){            return name;        }    }

输出结果如下:

AA

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); // trueSystem.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方法

原创粉丝点击