zoukankan      html  css  js  c++  java
  • Java 基础之 Object

    方法摘要

    public final native Class<?> getClass() //获取对象的运行时对象的类
    
    public native int hashCode()        //获取对象的 hash 值
    
    public boolean equals(Object obj)   //比较两个对象是否相等
    
    protected native Object clone()     //创建并返回一个对象的拷贝
    
    public String toString()    //返回对象的字符串表示形式。 
    
    public final native void notify()   //唤醒在该对象上等待的某个线程
    
    public final native void notifyAll()    //唤醒在该对象上等待的所有线程
    
    public final void wait()    //让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 
    
    public final native void wait(long timeout)  //让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间。 
    
    public final void wait(long timeout, int nanos)  //与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。。 
    
    protected void finalize()   //当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。
    

    equals()

    等价关系

    • 自反性
    x.equals(x) //true
    
    • 对称性
     x.equals(y) == y.equals(x) //true
    
    • 传递性
    x.equals(y) //true
    y.equals(z) //true
    x.equals(z) //true
    
    • 一致性
      多次调用 equals() 方法结果不变
    x.equals(y) == x.equals(y); // true
    
    • 与 null 的比较
      对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false
    x.equals(null); // false;
    

    等价与相等

    • 对于基本类型,==判断两个值是否相等,基本类型没有 equals() 方法
    • 对于引用类型,==判断两个值的引用是否相等,而 equals() 方法判断引用的对象是否相等
    Integer x = new Integer(1);
    Integer y = new Integer(1);
    System.out.println(x.equals(y)); // true
    System.out.println(x == y);      // false
    

    实现

    • 检查是否为同一个对象的引用,如果是直接返回 true;
    • 检查是否是同一个类型,如果不是,直接返回 false;
    • 将 Object 对象进行转型;
    • 判断每个关键域是否相等。
    public class EqualExample {
    
        private int x;
        private int y;
        private int z;
    
        public EqualExample(int x, int y, int z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
    
            EqualExample that = (EqualExample) o;
    
            if (x != that.x) return false;
            if (y != that.y) return false;
            return z == that.z;
        }
    }
    

    hashCode()

    hashCode 用于获取对象的 hash 值,表示在哈希表中的位置。

    equals() 方法判断两个对象是否等价,等价的两个对象哈希值一定相等,而哈希值相等的两个对象不一定等价,因为计算哈希值具有随机性。

    在覆盖 object 的 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也是相等的

    String 和 ArrayList 类都重写了 Object 的 equals() 方法,并重写了 hashCode() 方法

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        
        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;
        }   
        
        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;
        }    
    }
    
    

    重写 hashCode 方法时,需要用素数31作为乘子,因为31可以被 JVM 优化

    • 左移 << : 左边的最高位丢弃,右边补全0(把 << 左边的数据*2的移动次幂)。
    • 右移 >> : 把>>左边的数据/2的移动次幂。
    • 无符号右移 >>> : 无论最高位是0还是1,左边补齐0。

    所以 :31 * i = (i << 5) - i(左边 31 * 2=62,右边2 * 2^5-2=62)两边相等,JVM就可以高效的进行计算

    toString

    toString() 方法用于返回对象的字符串表示形式。默认返回格式:对象的 class 名称 + @ + hashCode 的十六进制字符串。

       public static void main(String[] args) {
           A a = new A();
           System.out.println(a.toString());    //client.A@b4c966a
       }
    

    clone()

    1. cloneable

    clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。

    public class A {
    
       public static void main(String[] args) {
           A a = new A();
           a.clone();   //Unhandled exception: java.lang.CloneNotSupportedException
       }
    }
    

    重写 clone() 方法,必须实现 Cloneable,因为 Cloneable 接口规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 java.lang.CloneNotSupportedException

    public class A implements Cloneable {
    
        private int a;
        private int b;
    
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            A a = new A();
            a.clone();
        }
    }
    

    2. 浅拷贝

    拷贝对象和原始对象的引用类型引用同一个对象。

    public class A implements Cloneable {
    
        private int arr;
    
        public int getArr() {
            return arr;
        }
    
        public void setArr(int arr) {
            this.arr = arr;
        }
    
        @Override
        public A clone() throws CloneNotSupportedException {
            return (A) super.clone();
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            A a = new A();
            a.setArr(123);
            A a1 = null;
            a1 = a.clone();
            System.out.println(a1.getArr()); //123
        }
    }
    

    3. 深拷贝

    拷贝对象和原始对象的引用类型引用不同对象。

    public class A implements Cloneable {
    
        private int arr;
    
        public int getArr() {
            return arr;
        }
    
        public void setArr(int arr) {
            this.arr = arr;
        }
    
        @Override
        public A clone() throws CloneNotSupportedException {
            A result = (A) super.clone();
            result.arr = this.arr;
            return result;
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            A a = new A();
            a.setArr(123);
            A a1 = null;
            a1 = a.clone();
            System.out.println(a1.getArr()); //123
        }
    }
    

    4. clone() 的替代方案

    使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。

    public class A {
    
        private int arr;
    
        public int getArr() {
            return arr;
        }
    
        public void setArr(int arr) {
            this.arr = arr;
        }
    
        public A() {
        }
    
        public A(A a) {
            this.arr = a.arr;
        }
    
        public static void main(String[] args){
            A a = new A();
            a.setArr(123);
            A a1 = new A(a);
            System.out.println(a1.getArr());    //123
        }
    }
    
  • 相关阅读:
    js 匿名函数的链式调用
    mysql 数据库操作的一般操作命令
    js 截取一定数量的字节
    js 截取10个字节
    BootStrap入门教程 (四)
    安装Dedecms遇到的一系列问题
    BootStrap入门教程 (三)
    dedecms标签调用大全
    artDialog皮肤引入方式
    织梦cms安装完成后登录后台出现空白。主要原因是php版本的问题
  • 原文地址:https://www.cnblogs.com/breakfei/p/14085631.html
Copyright © 2011-2022 走看看