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
方法用于克隆一个和该对象完全一样的新对象