浅谈Object
《一》前言
我们都知道Object是所有类的父类,任何类都默认继承Object类。
《二》方法解析:
1.hashCode():用来返回其所在对象的物理地址,也就是哈希码值,该方法用于哈希查找。
2.equal():用来判断对象的值是否相等,若是值相同但是在不同的内存地址,返回的是false.
如果希望不同内存但相同内容的两个对象equals时返回true,则我们需要重写父类的equal方法
举几个例子方便理解:
public class Main5 { public static void main(String[] args) { String s1 = new String("bgvhvhg"); String s2 = new String("bgvhvhg"); String str1 = new String("hjgb"); String str2 = "hjgb"; Integer i = 1; Integer j = 1; Integer m = 1; Integer n = new Integer(1); System.out.println(s1.equals(s2)); System.out.println(str1.equals(str2)); System.out.println(i.equals(j)); System.out.println(m.equals(n)); } }
执行结果:
3.clone():创建此对象的副本,注意:它是protected的,保证只有本类才可以复制本类对象。
4.toString():返回对象的字符串表示形式。通常,toString()方法返回一个“文本表示”此对象的字符串。
类Object的toString()方法返回一个字符串,该字符串包含类对象是实例的类的名称,at符号字符’@‘和此
对象的哈希码的无符号十六进制表示。即:getClass().getName() + '@' + Integer.toHexString(hashCode())。
5.notify():唤醒正在等待此对象的监视器的单个线程。如果任何线程正在等待此对象,则选择其中一个被唤醒。
选择是任意的,由程序实施自行决定。线程通过调用wait()方法之一等待对象的监视器。唤醒的线程将
无法继续,直到当前线程放弃此对象上的锁定。唤醒的线程将以通常的方式与可能主动竞争同步此
对象的任何其他线程竞争;例如,唤醒线程在下一个锁定此对象的线程中没有可靠的特权或劣势。
此方法只应由作为此对象监视器的所有者的线程调用。线程以三种方式之一成为等待对象监视器的所有者:
(1)通过执行该对象的同步实例方法。(2)通过执行在对象上同步的synchronized语句的主体。
(3)对于{ Class}类型的对象,通过执行该类的*synchronized静态方法。
6.notifyAll():唤醒等待此对象监视器的所有线程。 线程通过调用{ wait}方法之一等待对象的监视器。他的方法只能由
一个线程调用,该线程是该对象监视器的所有者。
7.wait():导致当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法,或者已经过了指定的时间。
当前线程必须拥有此对象的监视器。此方法导致当前线程将线程置于此对象的等待集中,然后放弃此对象上的任何
和所有同步声明。因线程调度而被禁用,并且在发生以下四种情况之一之前处于休眠状态:
(1)其他一些线程为此对象调用{notify}方法,并且线程碰巧被任意选为要唤醒的线程。
(2)其他一些线程为此对象调用{ notifyAll}方法。
(3)其他一些线程被中断。 (4)指定的实时数量已经或多或少。
但是,如果*{timeout}为零,则不考虑实时时间,并且线程只是等待通知。
8.finalize():该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用
《三》常见问题:
1.“==” 和equals()的区别:
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
由equals的源码可以看出这里定义的equals与==是等效的(Object类中的equals没什么区别),不同的原因就在于有些类(像String、Integer等类)对equals进行了重写,但是没有对equals进行重写的类(比如我们自己写的类)就只能从Object类中继承equals方法,其equals方法与==就也是等效的,除非我们在此类中重写equals。
对equals重写需要注意五点:
1 自反性:对任意引用值x,x.equals(x)的返回值一定为true;
2 对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
3 传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true ;
4 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变;
5 非空性:任何非空的引用值x,x.equals(null)的返回值一定为false 。
2.为什么wait()方法是在Object类中而不是在Thread类中?
因为我们的锁是对于对象而言的,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。
3.wait()和sleep()的区别:
本质区别为:
wait():释放资源,释放锁
sleep():释放资源,不释放锁
但是wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException(但不建议使用该方法)。在sleep()休眠时间期满后,该线程不一定会立即执行,这是因为其它线程可能正在运行而且没有被调度为放弃执行,除非此线程具有更高的优先级。wiat()必须放在synchronized block中