看一下API中关于Object的介绍:

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

那么Object中到底有哪些方法,各自有什么应用呢?
这个问题也经常出现在面试中,如果平时没有关注,可能很难回答好,这里简单整理一下。

首先看一下java.lang.Object的源码:

public class Object {
private static native void registerNatives();
static {
registerNatives();
}
/**
* 创建并返回此对象的副本。
* “复制”的准确含义可能根据对象的不同有变化。
*/
public final native Class<?> getClass(); /**
* 1.在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,
* 前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
* 2.如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
* 3.如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode方法不 要求一定生成不同的整数结果
* 但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
*/
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
} protected native Object clone() throws CloneNotSupportedException; /**
* 返回该对象的字符串表示
*/
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
} public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
/**
* 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
*/
protected void finalize() throws Throwable { }
}

源码的注释非常详细,现在针对这几个方法做分析。

>>hashCode()和equals(Object obj)方法

public native int hashCode();

native关键字表示该方法不是用java实现的,JDK源码中并不包含,对于不同的平台,这部分的实现也是不同的。

Java要实现对底层的控制,就需要其他语言的帮助,JVM将控制调用本地方法的所有细节。

hashCode方法的说明是:

Whenever it is invoked on the same object more than once during an execution of a Java application,the hashCode method must consistently return the same integer.

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

the programmer should be aware that producing distinct integer results
for unequal objects may improve the performance of hash tables.
开发人员应该知道,为不相等的对象产生不同的整数结果可能会提高哈希表的性能。
(这句没理解,再看)

This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java programming language.
hashcode一般是通过将该对象的内部地址转换成一个整数来实现的,不需要使用Java实现。

再来看equals()方法:

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

java中==运算符作用在基本数据类型和引用数据类型是不同的,
基本数据类型 byte, short, char, int, long, float, double, boolean
他们之间的比较,应用双等号(==),比较的是他们的值。

引用数据类型用(==)进行比较的时候,
比较的是在内存中的存放地址,所以,除非是实例化的同一个对象比较后的结果才为true,否则比较后结果为false。
注意一下,String,Integer,Date这些类重写了equals()方法,不再是比较类在堆内存中的存放地址了。

以String为例:

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

可以看到String对内部的字符数组进行了逐个字符的判断是否相等,

《Effective JAVA》中认为,99%的情况下,当你覆盖了equals方法后,请务必覆盖hashCode方法。

重写hashcode()方法:

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

当equals()方法被重写时,通常需要重写 hashCode 方法,以维护在hashCode 方法最开始的声明,即相等对象必须具有相等的哈希码。

1.notify()/notifyAll()和wait()

wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。
而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。

wait(),notify() 和 notifyAll() 可以让线程协调完成一项任务。例如,一个线程生产,另一线程消费。生产线程不能在前一产品被消费之前运行,而应该等待前一个被生产出来的产品被消费之后才被唤醒,进行生产。同理,消费线程也不能在生产线程之前运行,即不能消费不存在的产品,所以应该等待生产线程执行一个之后才执行。利用这些方法,就可以实现这些线程之间的协调。

来看一个例子:

public class WTThread extends Thread{
public WTThread(String name) {
super(name);
} public void run() {
//同步锁
synchronized (this) {
System.out.println(Thread.currentThread().getName()+" call notify()");
/**
* 这个线程执行的过程中会去唤醒当前对象的wait线程
*/
notify();
}
}
}

 主线程的执行方法:

public class UseWaitNotify {

	public static void main(String[] args) throws InterruptedException{
WTThread t1=new WTThread("t1");
//同步锁
synchronized(t1) {
//启动线程t1
System.out.println(Thread.currentThread().getName()+" start t1");
t1.start(); /**
* 主线程进入等待状态
* 同时wait()释放主线程持有的同步锁
*/
System.out.println(Thread.currentThread().getName()+" wait()");
t1.wait();
/**
* 主线程等待后,释放了锁,t1线程就可以执行了
* 于是会操作 下面的执行体
* System.out.println(Thread.currentThread().getName()+" call notify()");
* notify();
*/
/**
* t1执行完毕后,唤醒主线程,主线程持有锁,继续执行
* 打印查看目前正在执行的线程
*/
System.out.println(Thread.currentThread().getName()+" continue");
}
}
}

  控制台输出:

main start t1
main wait()
t1 call notify()
main continue

这段代码来自这篇文章,Java多线程系列--“基础篇”05之 线程等待与唤醒

这几个方法也都是native的,是调用的系统底层方法实现。

2.不同的wait()方法有什么区别

查看源码可以发现这里有三个不同wait方法:

public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {}
public final void wait() throws InterruptedException {
wait(0);
}

没有参数的 wait() 方法被调用之后,线程就会一直处于等待状态,直到本对象(就是 wait() 被调用的那个对象)调用 notify() 或 notifyAll() 方法。
相应的,wait(long timeout) 和wait(long timeout, int nanos) 方法中,
当等待时间结束或者被唤醒(无论哪一个先发生)时将会结束等待。

3.finalize()方法

/**
* Called by the garbage collector on an object when garbage collection
* determines that there are no more references to the object.
*/
protected void finalize() throws Throwable { }

可以看到这个方法是protected的。

特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。
一般来说,不推荐使用finalize()方法,它跟析构函数不一样。

4.getClass()方法

/**
* Returns the runtime class of this Object.
* The returned Class object is the object that is locked by
* "static""synchronized" methods of the represented class.
*/
public final native Class<?> getClass();

返回这个Object对象的运行时类。

5.clone()方法

clone方法就是复制对象。所谓的复制对象,就是要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象。
这里涉及到浅拷贝和深拷贝的关系:

Person p = new Person(23, "zhang");
Person p1 = p;

这段代码中,P和P1其实是引用,指向同一个对象。

Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();

但是这段代码是创建了两个相同的对象,P和P1的引用分别指向不同的对象,

但是Clone执行的方法是浅拷贝,需要注意这个,P和P1里的name字段指向的是同一块堆内存。

具体的可以查看这篇文章:
详解Java中的clone方法

6.toString()方法

返回对象表示的字符串,实际上我们应用的都是对这个类的重写。

对Object类中方法的深入理解的更多相关文章

  1. Object类中方法详解

    目录 概述 hashCode方法 getClass方法 toString方法 equals方法 clone方法 finalize方法 概述 Object 是类层次结构的根类.每个类都使用 Object ...

  2. Object类clone方法的自我理解

    网上搜帖: clone()是java.lang.Object类的protected方法,实现clone方法: 1)类自身需要实现Cloneable接口 2)需重写clone()方法,最好设置修饰符mo ...

  3. Java:面向对象(继承,方法的重写(overide),super,object类及object类中方法的重写,父子类代码块执行顺序)

    继承: 1.继承是对某一匹类的抽象,从而实现对现实世界更好的建模. 2.提高代码的复用性. 3.extends(扩展),子类是父类的扩展. 4.子类继承父类可以得到父类的全部属性和方法.(除了父类的构 ...

  4. java Object类中方法介绍

  5. 【Java基础之Object类(一)】Java中Object类中的所有方法(toString、equals、hashCode、clone、finalize、wait和notify等)详解(转载)

    java中的hashcode.equals和toString方法都是基类Object的方法. 首先说说toString方法,简单的总结了下API说明就是:返回该对象的字符串表示,信息应该是简明但易于读 ...

  6. Object类中wait代餐方法和notifyAll方法和线程间通信

    Object类中wait代餐方法和notifyAll方法 package com.yang.Test.ThreadStudy; import lombok.SneakyThrows; /** * 进入 ...

  7. 重写Object类中的equals方法

    Object是所有类的父亲,这个类有很多方法,我们都可以直接调用,但有些方法并不适合,例如下面的student类 public class Student { //姓名.学号.年纪 private S ...

  8. Java基础(43):Java中的Object类与其方法(转)

    Object类 java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. O ...

  9. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

随机推荐

  1. python 函数的文档字符串 docstrings

    函数体的第一行可以是一个可选的字符串文本:此字符串是该函数的文档字符串,或称为docstring.(更多关于 docstrings 的内容可以在 文档字符串一节中找到.)有工具使用 docstring ...

  2. block 在ARC和非ARC下的不同含义

    Block的循环引用 对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中使用的对象: 对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中使用的对 ...

  3. HTTP头部详解

    因为之后的HTTP头注入要学习这些所以就看了.觉得很不错,算是学习前的科普. <HTTP头部详解>转载自:http://www.cnblogs.com/lcamry/p/5763040.h ...

  4. OpenCV成长之路(3):模仿PhotoShop中魔术棒工具

    本文的主题实际上是图像的颜色空间的转换,借助一个颜色选取程序来说明OpenCV中颜色转换函数的用法以及一些注意事项. 一.几种常见的颜色空间: RGB颜色空间:RGB采用加法混色法,因为它是描述各种“ ...

  5. Javascript——Context和Scope的一些学习总结

    1.1.1 摘要 在我们学习Javascript过程中,常常会遇到作用域(Scope)和执行上下文(Context)等概念.其中,执行上下文与this关键字的关系密切. 有面向对象编程经验的各位,对于 ...

  6. C#之Textbox实现自动提示容、自动补齐内容

    今发现一个博文挺有意思,实现的功能很有意思但方法却很简单,特此转过来,以备以后查阅. 先上原博文地址:http://blog.csdn.net/testcs_dn/article/details/45 ...

  7. Python模块之optparse

    参考: http://www.cnblogs.com/captain_jack/archive/2011/01/11/1933366.html https://docs.python.org/2/li ...

  8. Appium+Robotframework实现Android应用的自动化测试-3:一个必不可少的工具介绍

    万事具备,接下来我们就要开始编写测试脚本了. 不过,有个重要的问题还没有解决.我们知道RobotFramework在web 网页中主要依靠元素的id,name或者xpath来定位页面上的元素,我们依赖 ...

  9. 安装m2crypto报错swig error : Unrecognized option -builtin

    M2Crypto 是最完整的为 Python 包装 OpenSSL 的 RSA,DSA,DH,EC,HMACs,消息摘要,对称密码算法(包括AES)的一个库工具.而自从 M2Crypto 升级到版本 ...

  10. bbs/贴吧/盖楼的技术实现(PHP)

    2015年3月5日 14:36:44 更新: 2015年7月18日 16:33:23 星期六 目标, 实现类似网易盖楼的功能, 但是不重复显示帖子 效果: * 回复 //1楼 ** 回复 //1楼的子 ...