深入浅出Java Object源码

Java中的Object

Java中的Object类位于java.lang包中,每一个Java类直接或者间接继承自Object,如果一个类没有继承任何类,那么该类默认直接继承Object,如果一个类继承了某一个类,那么Object间接继承了Object,因此所有Java对象都可以访问Object中定义的方法,因此Object是所有类的顶级父类。

Object源码解析

toString方法,返回该对象的String表示,Object中的toString方法返回类名+@+hashCode的无符号16进制

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

推荐开发中一般都会重写子类中的toString方法,使其更有意义,注意当输入对象时,默认调用对象的toString方法

Student s = new Student();

// Below two statements are equivalent
System.out.println(s);
System.out.println(s.toString());

println源码如下

/**
 * Prints an Object and then terminate the line.  This method calls
 * at first String.valueOf(x) to get the printed object's string value,
 * then behaves as
 * though it invokes <code>{@link #print(String)}</code> and then
 * <code>{@link #println()}</code>.
 *
 * @param x  The <code>Object</code> to be printed.
 */
public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

hashCode方法详解,对于每一个对象,JVM生成一个独一无二的数字-hashCode,它为不同的对象返回不同的整数,一个普遍错误的理解就是该方法返回对象的内存地址,这样的理解是不对的,他使用某种算法把对象内存地址转换为整数,即hashCode,hashCode方法是native的,因为java无法操作内存地址,所以java底层是使用C/C++访问对象的内存地址,故他的源码无法观看,你需要下载openjdk才可以查看源码
hashCode的使用: 返回用于搜索集合中的对象的哈希值。 JVM(Java虚拟机)使用哈希码方法,同时将对象保存为散列相关的数据结构,如HashSet,HashMap,Hashtable等。基于哈希码保存对象的主要优点是搜索变得容易。

public native int hashCode();

不能根据hashCode值判断是否是同一个对象,如以下代码,虽然他们的hashCode是一样的,但是他们不是同一个对象

String firstStr = new String("hashCode");
String secondStr = new String("hashCode");

System.out.println(firstStr == secondStr); //false
System.out.println(firstStr.hashCode()); //147696667
System.out.println(secondStr.hashCode()); //147696667

为什么他们的hashCode是一样的呢,看源码如下

/**
 * Returns a hash code for this string. The hash code for a
 * {@code String} object is computed as
 * <blockquote><pre>
 * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
 * </pre></blockquote>
 * using {@code int} arithmetic, where {@code s[i]} is the
 * <i>i</i>th character of the string, {@code n} is the length of
 * the string, and {@code ^} indicates exponentiation.
 * (The hash value of the empty string is zero.)
 *
 * @return  a hash code value for this object.
 */
public int hashCode() {
    //hash默认是0
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        //s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

为什么源码中使用了质数31,这里找了一片博文why 31
所以从源码得出,相同的字符串内容的hashCode的值是一样的,即使他们不是同一个对象,再看以下比较特殊的几个例子,结果看源码就可以知道了

System.out.println("".hashCode()); //0
System.out.println("a".hashCode()); //97
System.out.println("A".hashCode()); //65
System.out.println("aA".hashCode()); // 3072

equals方法,Object默认是判断是否是同一个对象,所以如果子类没有重写,默认比较是否是同一个对象

public boolean equals(Object obj) {
    return (this == obj);
}

例子

Object object = new Object();

System.out.println(object.equals(object)); //true
System.out.println(object.equals(null)); //false

getClass方法,返回“this”对象的类对象,用于获取对象的实际运行时类。它还可用于获取此类的元数据。返回的Class对象是由所表示的类的静态同步方法锁定的对象。因为它是final的所以我们不会覆盖它。

Object obj = new String("github/shellhub");
Class cls =obj.getClass();
System.out.println(cls.getName());

finalize()方法,在对象被垃圾收集之前调用此方法。当垃圾收集器确定没有对该对象的更多引用时,垃圾收集器会在对象上调用它。我们应该覆盖finalize()方法来处理系统资源,执行清理活动并最小化内存泄漏。例如,在销毁Servlet对象web容器之前,总是调用finalize方法来执行会话的清理活动。
注意:即使该对象有多次符合垃圾回收条件,对象也只调用一次finalize方法。

public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.hashCode());

        t = null;

        // calling garbage collector
        System.gc();
        System.out.println("end");
    }

    @Override
    protected void finalize() {
        System.out.println("finalize method called");
    }
}

注意finalize方法不一定会执行,多试几次

clone方法用于克隆一个和该对象完全一样的新对象

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值