浅谈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中

 

posted @ 2019-08-29 14:38  离愁i  阅读(288)  评论(0编辑  收藏  举报