Java Object类 hashcode、 equals 、 toString、notify()、notifyAll()、finalize()

Object类是所有类、数组、枚举类的父类,是类层次结构的根类。每个类都使用Object作为超类。所有对象(包括


数组)都实现这个类的方法


1  Object.hashCode() 就是一个哈希函数,用来计算散列值以实现哈希表这种数据结构。

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。


hashCode 的常规协定是:

1、在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提


将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,


该整数无需保持一致。


2、如果根据equals (object)方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashcode方法都必须生成相同的整数结果。


3、如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode

方法 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高


哈希表的性能。


总结:equals (object)方法,两个对象是相等的 那么hashcode方法都必须生成相同的整数结果

           equals (object)方法,两个对象是不相等的 那么hashcode方法可能相同可能不相同


在实际开发中,除了重写了hasCode()方法时,还要重写equals()方法。

2  equals()方法

  1. public boolean equals(Object obj) {  

  2.         return (this == obj);  
  3.     }

我们从以上程序中可以看出equals()方法的作用就是与某个对象进行比较,是否相等。


equals 方法在非空对象引用上实现相等关系:

1、自反性:对于任何非空引用值xx.equals(x) 都应返回true


2、对称性:对于任何非空引用值x 和y,当且仅当y.equals(x) 返回true 时,x.equals(y) 才应返回true


3、传递性:对于任何非空引用值xy 和z,如果x.equals(y) 返回true,并且y.equals(z) 返回true,那么x.equals(z)


应返回 true


4、一致性:对于任何非空引用值x 和y,多次调用x.equals(y) 始终返回true 或始终返回false,前提是对象上


equals 比较中所用的信息没有被修改。


5、对于任何非空引用值 xx.equals(null) 都应返回false


Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值x 和y,当且仅当x


和 y 引用同一个对象时,此方法才返回 truex == y 具有值true)。


注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等


对象必须具有相等的哈希码。


3 toString()方法


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

通过以下程序可以看出toString()方法返回的是这个类的全称限定名加上“@”符号,最后加上这个对象的哈希值,并将


哈希值转换成十六进制输出。

在平时我们可以通过toString()方法,获取该对象信息的字符串,比如:

  1. class User {  
  2.     private String name;  
  3.     private int age;  
  4.       
  5.     public User(String name,int age){  

  6.         this.name=name;  
  7.         this.age=age;  
  8.     }  
  9.       
  10.     protected String getName() {  
  11.         return name;  
  12.     }  
  13.   
  14.     public void setName(String name) {  
  15.         this.name = name;  
  16.     }  
  17.   
  18.   
  19. }  
  20. public class Main {  
  21.       
  22.     public static void main(String[] args) {  
  23.         User user=new User("Bill",25);  
  24.         System.out.println(user.toString());  
  25.     }  
  26.   


输出:

code2.User@1db9742


除了直接使用toString()方法外,我们还可以重载这个方法,比如:

  1. class User {  

  2.     private String name;  
  3.     private int age;  
  4.       
  5.     public User(String name,int age){ 
  6.  
  7.         this.name=name;  
  8.         this.age=age;  
  9.     }  
  10.       
  11.     protected String getName() {  
  12.         return name;  
  13.     }  
  14.   
  15.     public void setName(String name) {  
  16.         this.name = name;  
  17.     }  
  18.       
  19.     @Override  
  20.     public String toString() {  

  21.         return "name="+name+"\nage="+age;  
  22.     }  
  23.   
  24.   
  25. }  
  26. public class Main {  
  27.       
  28.     public static void main(String[] args) {  
  29.         User user=new User("Bill",25);  
  30.         System.out.println(user.toString());  
  31.     }  
  32.   


输出:

name=Bill
age=25


4 notify():

  1. public final native void notify();  


notify()的方法说明:


唤醒在此对象监视器上等待的单个线程如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个wait 方法,在对象的监视器上等待。


直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同


步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。


此方法只应由作为此对象监视器的所有者的线程来调用。通过以下三种方法之一,线程可以成为此对象监视器的所


有者:

  • 通过执行此对象的同步实例方法。
  • 通过执行在此对象上进行同步的 synchronized 语句的正文。
  • 对于 Class 类型的对象,可以通过执行该类的同步静态方法。

一次只能有一个线程拥有对象的监视器。


5 notifyAll():


  1. public final native void notifyAll();  

 

notifyAll()的方法说明:


唤醒在此对象监视器上等待的所有线程。线程通过调用其中一个 wait 方法,在对象的监视器上等待。


直到当前线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同


步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。


此方法只应由作为此对象监视器的所有者的线程来调用。有关线程能够成为监视器所有者的方法的描述,请参阅


notify 方法。


6 finalize()


[java]  view plain copy
  1. protected void finalize() throws Throwable { } 

关于此方法的说明:


当系统中没有引用变量引用到该对象时,垃圾回收器调用此方法来清理该对象的资源。

finalize 的常规协定是:当 JavaTM 虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时,将调用


此方法,除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize 方法可以采取任何操作,其


中包括再次使此对象对其他线程可用;不过,finalize 的主要目的是在不可撤消地丢弃对象之前执行清除操作。例


如,表示输入/输出连接的对象的 finalize 方法可执行显式 I/O 事务,以便在永久丢弃对象之前中断连接。


Object 类的 finalize 方法执行非特殊性操作;它仅执行一些常规返回。Object 的子类可以重写此定义。


Java 编程语言不保证哪个线程将调用某个给定对象的 finalize 方法。但可以保证在调用 finalize 时,调用 finalize


 的线程将不会持有任何用户可见的同步锁定。如果 finalize 方法抛出未捕获的异常,那么该异常将被忽略,并且该对


象的终结操作将终止。


在启用某个对象的 finalize 方法后,将不会执行进一步操作,直到 Java 虚拟机再次确定尚未终止的任何线程无法


再通过任何方法访问此对象,其中包括由准备终止的其他对象或类执行的可能操作,在执行该操作时,对象可能被


丢弃。


对于任何给定对象,Java 虚拟机最多只调用一次 finalize 方法。


finalize 方法抛出的任何异常都会导致此对象的终结操作停止,但可以通过其他方法忽略它。


你可能感兴趣的:(Java)