zoukankan      html  css  js  c++  java
  • Java 常用类(一):根父类——Object

    一、Object 类的概述

      java.lang.Object 类是 Java 语言中的根类,即所有类的父类,所有的类都直接或间接的继承 Object 类。

      在对象实例化的时候,最终的父类就是 Object。

      如果在类的声明中未使用extends关键字指明其父类, 则默认父类为java.lang.Object

      Demo:

    1 public class MyClass{
    2       // ...
    3 }
    4 
    5 等价于
    6 public class MyClass extends Object{
    7     ...
    8 }

      Object类中方法:

      

    二、Object方法

      1、构造方法

    public Object()

      2、registerNatives 方法

    private static native void registerNatives();  //私有的本地方法
    static {
      registerNatives();
    }

      3、getClass 方法

    public final native Class<?> getClass();
    

            该方法是为了获取此 Object 的运行类。(反射时详细学习)

      4、hashCode 方法

    public native int hashCode();
    

          该方法是为了获取该的 hashCode(哈希) 值;

        注意:在 Java 中hancode 与 对象是否相等密切相关。如果两个对象相等,则 hashcode 一定相等,但是 hashcode 相等,两个对象不一定相等。如果 hashcode 不相等,那么这两个对象一定不相等。

      5、equals 方法

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

        该方法是用于确认两个对象是否“相同”。

      6、clone 方法

    protected native Object clone() throws CloneNotSupportedException;
    

        创建并返回此对象的一个副本。

      7、toString 方法

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

        该方法用于打印此对象的“全类名@此对象在内存中地址值(十六进制)”;

      8、notify、notifyAll、wait、等方法与线程相关

    public final native void notify();    //唤醒在此对象监视器上等待的单个线程。
    public final native void notifyAll();  //唤醒在此对象监视器上等待的所有线程。

     //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或 者超过指定的时间量前,导致当前线程等待。 public final native void wait(long timeout) throws InterruptedException;
    //用于让当前线程失去操作权限,当前线程进入等待序列 public final void wait() throws InterruptedException { wait(0); }
     //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。 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 > 0) { timeout++; } wait(timeout); }

      9、finalize

    protected void finalize() throws Throwable { }
    

         当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

    三、方法详解

      1、registerNatives 方法

          native 关键字与 registerNatives 方法

      2、== 操作符与 equals 方法 (常见面试题)

        (1)== 操作符

           a、对于基本数据类型来说,比较两个值,只要两个变量的值相等,即为 true;

    int a=a;
    if (a ==6){...}
    

      

           b、对于引用类型比较引用(是否指向同一个对象);只有指向同一个对象,== 才返回 true;

    Person p1 = new Person();
    Person p2 = new Person();
    if (p1 == p2) {...}
    

            注意:用“==” 进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错。

        (2)equals 方法

          [1] equals:所有类都继承了 Object,也就获得了 equals() 方法。还可以重写。

          •  只能比较引用类型,其作用域 “==” 相同,比较是否执行同一个对象;

          [2] 默认比较:如果没有覆盖重写 equals 方法,那么 Object 类中默认进行 == 运算符的对象地址比较,只要不是同一个对象,结果为 false。

          equals 方法源码:

          

            参数:

            Object  obj :可以传递任何的对象

            == 比较运算符,返回的是一个布尔值 true false

            基本数据类型:比较的是值

            引用数据类型:比较的是两个对象的地址值。

          [3] 特例:当用 equals() 方法进行比较时,对类 File、String、Date 及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个引用对象。

            原因:在这些类中重写了 Object 类的 equals() 方法。

          [4] 当自定义使用 equals() 时,可以重写,用于比较两个对象的“内容”是否都相等。

          重写 equals() 方法的原则:

    对称性:如果 x.equals(y) 返回是 “true”, 那么 y.equals(x) 也应该返回是 “true” 。

    自反性:x.equals(x)必须返回是“true” 。

    传递性:如果x.equals(y)返回是“true” , 而且y.equals(z)返回是“true” ,那么z.equals(x)也应该返回是“true”。

    一致性:如果x.equals(y)返回是“true” , 只要xy内容一直不变, 不管你重复x.equals(y)多少次, 返回都是“true” 。

    任何情况下, x.equals(null), 永远返回是“false” ;
    x.equals(x不同类型的对象)永远返回是“false” 。

         通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们就需要对Object类中的equals()进行重写,重写的原则:比较两个对象的实体内容是否相同。

        重写 equals() 方法Demo:

     1 public class Customer {
     2     
     3     private String name;
     4     private int age;
     5     public String getName() {
     6         return name;
     7     }
     8     public void setName(String name) {
     9         this.name = name;
    10     }
    11     public int getAge() {
    12         return age;
    13     }
    14     public void setAge(int age) {
    15         this.age = age;
    16     }
    17     public Customer() {
    18         super();
    19     }
    20     public Customer(String name, int age) {
    21         super();
    22         this.name = name;
    23         this.age = age;
    24     }
    25 
    26     //自动生成的equals()
    27     @Override
    28     public boolean equals(Object obj) {
    29         if (this == obj)
    30             return true;
    31         if (obj == null)
    32             return false;
    33         if (getClass() != obj.getClass())
    34             return false;
    35         Customer other = (Customer) obj;
    36         if (age != other.age)
    37             return false;
    38         if (name == null) {
    39             if (other.name != null)
    40                 return false;
    41         } else if (!name.equals(other.name))
    42             return false;
    43         return true;
    44     }
    45     
    46     
    47     
    48     //重写的原则:比较两个对象的实体内容(即:name和age)是否相同
    49     //手动实现equals()的重写
    50     /*
    51     @Override
    52     public boolean equals(Object obj) {
    53         
    54 //      System.out.println("Customer equals()....");
    55         if (this == obj) {
    56             return true;
    57         }
    58         
    59         if(obj instanceof Customer){
    60             Customer cust = (Customer)obj;
    61             //比较两个对象的每个属性是否都相同
    62 //            if(this.age == cust.age && this.name.equals(cust.name)){
    63 //                return true;
    64 //            }else{
    65 //                return false;
    66 //            }
    67             
    68             //或
    69             return this.age == cust.age && this.name.equals(cust.name);
    70         }else{
    71             return false;
    72             
    73         }
    74         
    75     }
    76     */
    77     
    78     //手动实现
    79     /*    
    80     @Override
    81     public String toString() {
    82         return "Customer[name = " + name + ",age = " + age + "]"; 
    83     }
    84     */
    85     
    86     //自动实现
    87     @Override
    88     public String toString() {
    89         return "Customer [name=" + name + ", age=" + age + "]";
    90     }
    91 }

        面试题:== 与 equals 的区别

        (1)== 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址;

        (2)equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。

        (3)具体要看自定义类里有没有重写Objectequals方法来判断;

        (4)通常情况下,重写equals方法,会比较类中的相应属性是否都相等;

        面试题:hashCode() 与 equals() 的区别

        (1)hashCode()方法和equal()方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致;

        (2)因为重写的equal()里一般比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高,那么hashCode()既然效率这么高为什么还要equal()呢?

        (3)因为hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠

      3、toString() 方法

        (1)toString()方法在Object类中定义, 其返回值是String类型, 返回类名和它的引用地址;

        (2)在进行String与其它类型数据的连接操作时, 自动调用toString()方法;

    Date now=new Date();
    System.out.println(“now=”+now); 相当于
    System.out.println(“now=”+now.toString());
    

      

        (3)可以根据需要在用户自定义类型中重写toString()方法String 类重写了toString()方法, 返回对象的"实体内容";

    s1=“hello”;
    System.out.println(s1);//相当于System.out.println(s1.toString());
    

      

        (4)基本类型数据转换为String类型时, 调用了对应包装类的toString()方法:

    int a=10; System.out.println(“a=”+a);
    

        面试题:

    1 public void test() {
    2     char[] arr = new char[] { 'a', 'b', 'c' };
    3     System.out.println(arr);//  abc
    4     int[] arr1 = new int[] { 1, 2, 3 };
    5     System.out.println(arr1);//   [I@15db9742
    6     double[] arr2 = new double[] { 1.1, 2.2, 3.3 };
    7     System.out.println(arr2);//   [D@6d06d69c
    8 }

        解析:下面的两个 println(Object x) 方法的形参是 Object,方法体内就是打印地址值;而当参数是  char 数组时,就调用对应的 println(char x[]) 方法,对该数组进行遍历输出。

          

      4、clone() 方法

          clone:对象的克隆(拷贝)

      5、finalize() 方法

        当垃圾回收器确定不再有对该对象的引用时,由垃圾回收器在对象上调用该方法。该方法只会被调用一次

        Demo:

     1 public class FinalizeTest {
     2     public static void main(String[] args) {
     3         Person p = new Person("Peter", 12);
     4         System.out.println(p);
     5         p = null;//此时对象实体就是垃圾对象,等待被回收。但时间不确定。
     6         System.gc();//强制性释放空间
     7     }
     8 }
     9 
    10 class Person{
    11     private String name;
    12     private int age;
    13 
    14     public Person(String name, int age) {
    15         super();
    16         this.name = name;
    17         this.age = age;
    18     }
    19     public String getName() {
    20         return name;
    21     }
    22     public void setName(String name) {
    23         this.name = name;
    24     }
    25     public int getAge() {
    26         return age;
    27     }
    28     public void setAge(int age) {
    29         this.age = age;
    30     }
    31     //子类重写此方法,可在释放对象前进行某些操作
    32     @Override
    33     protected void finalize() throws Throwable {
    34         System.out.println("对象被释放--->" + this);
    35     }
    36     @Override
    37     public String toString() {
    38         return "Person [name=" + name + ", age=" + age + "]";
    39     }
    40 }

        补充:垃圾回收机制关键点

    垃圾回收机制只回收JVM堆内存里的对象空间。

    对其他物理连接,比如数据库连接、输入流输出流、Socket连接无能为力

    现在的JVM有多种垃圾回收实现算法,表现各异。

    垃圾回收发生具有不可预知性,程序无法精确控制垃圾回收机制执行。

    可以将对象的引用变量设置为null,暗示垃圾回收机制可以回收该对象。

    程序员可以通过System.gc()或者Runtime.getRuntime().gc()来通知系统进行垃圾回收,会有一些效果,但是系统是否进行垃圾回收依然不确定。

    垃圾回收机制回收任何对象之前,总会先调用它的finalize方法(如果覆盖该方法,让一个新的引用变量重新引用该对象,则会重新激活对象)。

    永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。

    四、Objects 方法

        上面重写 equals 方法中,使用了 java.util.objects 类,下面对这个类进行了解。

         在 JDK7 添加了一个 Objects 工具类,它提供了一些方法来操作对象,它由一些静态的使用方法组成,这些方法是 null-save(空指针安全的) 或 null-tolerant(容忍空指针的),用于计算对象的 hashcode、返回对象的字符串表示形式、比较两个对象。

      在比较两个对象的时候,Object 的 equals 方法容易抛出空指针异常,而 Object 类中的 equals 方法优化了这个问题。

      方法如下

    public static boolean equals(Object a, Object b):判断两个对象是否相等。

       源码

    public static boolean equals(Object a, Object b) {  
        return (a == b) || (a != null && a.equals(b));  
    }
    

      有兴趣的可以仔细研读一下源码。

     

  • 相关阅读:
    Java8系列之重新认识HashMap(转)
    kafka 消费者和生产者测试类
    zookeeper配置
    JNLP应用程序无法打开的解决办法
    Functional Programming 资料收集
    Python的问题解决: IOError: [Errno 32] Broken pipe
    python的subprocess的简单使用和注意事项
    Python tricks(7) -- new-style class的__slots__属性
    Python tricks(6) -- python代码执行的效率
    Python tricks(5) -- string和integer的comparison操作
  • 原文地址:https://www.cnblogs.com/niujifei/p/13946367.html
Copyright © 2011-2022 走看看