• java中的Object类和其clone()


    1.Object是所有类的父类,任何类都默认继承Object,即直接或间接的继承java.lang.Object类。由于所有的类都继承在Object类,因此省略了
    extends Object关键字。

    2.Object类中主要有以下方法:

      toString()  getClass()  equals()  clone()  finalize()  notify()  notifyAll()  wait()

    其中toString(),getClass(),equals()是其中最重要的方法。getClass(),notify(),notifyAll(),wait()等方法被定义为final类型,因此不能重写。

    3.clone()方法

    public class Object  {
        protected native Object clone() throws CloneNotSupportedException;
    }

    (1) clone()存在的原因是Java里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递。可以在类中复写clone方法以实现深拷贝。
    (2) Object类的 clone() 方法是一个native方法,native方法的效率一般来说都是远高于Java中的非native方法。这也解释了为什么要用Object中clone()
    方法而不是先new一个类,然后把原始对象中的信息复制到新对象中。
    (3) 必须要重写clone()方法以达到在类外使用的目的。
    (4) Object.clone()方法返回一个Object对象, 必须进行强制类型转换才能得到我们需要的类型。

    在派生类中实现Cloneable接口。奇怪的发现Cloneable竟然是空的,它仅仅是一个标志,而且这个标志也仅仅是针对 Object类中 clone()方法的,如果 clone 类没有实现
    Cloneable 接口,并调用了 Object 的 clone() 方法(也就是调用了 super.Clone() 方法),那么Object 的 clone() 方法就会抛出
    CloneNotSupportedException 异常。

    clone使用demo1:

    class Person implements Cloneable { //clone()是Object类中的protected成员方法。继承Cloneable只是为了运行时不要报异常。
        private int age ;
        private String name;
        
        public Person(int age, String name) {
            this.age = age;
            this.name = name;
        }
        
        public Person() {}
     
        public int getAge() {
            return age;
        }
     
        public String getName() {
            return name;
        }
        
        /*
         * 这里必须要复写Object类的clone()方法,原因:
         * Object类中的clone()方法是protected权限,只能在本包中或者在其它包的子类中访问(注意是子类中)
         * 这里重写一下,虽然还是protected的,但是可以在本包中访问了。
         */
        @Override
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    
    public class Test {
        public static void main(String args[]) {
            Person p = new Person(23, "zhang");
            Person p1 = null;
            try {
                p1 = (Person) p.clone(); //非子类中访问clone()方法
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
    
            if (p1 != null) {
                System.out.println(p); //若引用的是同一个类,打印的hash值是一样的,clone的是不同的
                System.out.println(p1);    
            }
        }
    }
    View Code

    如果想要拷贝一个对象,这个对象必须要实现Cloneable接口,实现clone方法。

    clone使用demo2:

    public class CloneTest {
    
        static class Body implements Cloneable {
            /**/
            public Head head;
            public Body() {}
            public Body(Head head) { this.head = head; }
    
            @Override
            protected Object clone() throws CloneNotSupportedException {
                Body newBody =  (Body)super.clone();
                newBody.head = (Head)head.clone(); //
                return newBody;
            }
            
        }
            
        static class Head implements Cloneable {
            public Face face;
            public Head() {}
            public Head(Face face){ this.face = face; }
    
            @Override
            protected Object clone() throws CloneNotSupportedException {
                Head newHead = (Head)super.clone();
                newHead.face = (Face)face.clone(); // face.clone();相对于Face类来说在Face类外部,若Face类没有重写这个接口将报错
                return newHead;
            }
        } 
            
        static class Face implements Cloneable {
            @Override
            protected Object clone() throws CloneNotSupportedException {
                return super.clone();
            }
        }
    
        public static void main(String[] args) throws CloneNotSupportedException {
            
            Body body = new Body(new Head(new Face()));
            
            Body body1 = (Body) body.clone();
            
            System.out.println("body == body1 : " + (body == body1) );
            
            System.out.println("body.head == body1.head : " +  (body.head == body1.head));
            
            System.out.println("body.head.face == body1.head.face : " +  (body.head.face == body1.head.face));
            
            
        }
    }
    View Code

    若Face类不实现Cloneable接口,Head类中也不调用face.clone(),那么成员对象face传的还是引用!这就是一种不彻底的深拷贝。

    结论:如果想要深拷贝一个对象,这个对象必须要实现Cloneable接口,实现clone方法,并且在clone方法内部,把该对象成员变量中引用的其他对象也要clone一份,这就要求这个被成员对象引用的对象必须也要实现Cloneable接口并且重写clone方法。

    4.toString()方法

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

    一般子类重写这个方法以便打印自己想到的内容。

    5.getClass()方法

    public final native Class<?> getClass();

    返回此Object运行时类类型,final修饰不可重写,一般和getName()联合使用,如getName().getClass().

    6.finalize()方法

    protected void finalize() throws Throwable {}

    该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。

    关于垃圾回收,有三点需要记住:
    a.对象可能不被垃圾回收,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。
    b.垃圾回收并不等于“析构”。
    c.垃圾回收只与内存有关,使用垃圾回收的唯一原因是为了回收程序不再使用的内存。

    7.equals()方法

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

    直接判断的是引用,若想判断内容是否相同,需要重写此方法。

    8.hashCode()方法

    public native int hashCode();

    返回该对象的哈希值,该方法用于哈希查找.

    9.wait()方法

    public final native void wait() throws InterruptedException;
    public final native void wait(long timeout) throws InterruptedException; //超时时间timeout ms

    wait()方法一直等待,直到获得锁或者被中断。wait(timeout)如果在规定时间内没有获得锁就返回。

    调用该方法后当前线程进入睡眠状态,直到以下事件发生。
      a.其他线程调用了该对象的notify方法。
      b.其他线程调用了该对象的notifyAll方法。
      c.其他线程调用了interrupt中断该线程。
      d.时间间隔到了。

    注意:只有获取锁后wait()方法才起作用,没有获取锁调用wiat()方法无效。调用wait()方法后会释放线程锁,等待结束后重新获取锁继续执行。

    class A {
        public synchronized void printThreadInfo() throws InterruptedException
        {
            int i = 0;
    
            while (i++ < 5) {
                this.wait(1000);
                System.out.println("Still need wait resourse");
            }
        }
    }
    
    public class Test {
        public static void main(String args[]) {
            A a = new A();
            try {
                a.printThreadInfo();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    View Code
    public class WaitNotifyTest {
        public static void main(String[] args) {
            final Object lock = new Object(); //局部变量lock在内部类中访问了,需要加上final修饰
            
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程A等待获取lock锁");
                    synchronized (lock) {
                        try {
                            System.out.println("线程A获取了lock锁");
                            Thread.sleep(1000);
                            System.out.println("线程A将要运行lock.wait()方法进行等待");
                            lock.wait();
                            System.out.println("线程A等待结束");
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
            
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("线程B等待获取lock锁");
                    synchronized (lock) {
                        System.out.println("线程B获取了lock锁");
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("线程B将要运行lock.notify()方法进行通知");
                        lock.notify();
                    }
                }
            }).start();
        }
    }
    View Code

    JVM的一些函数使用了JNI

    static JNINativeMethod methods[] = {
        {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
        {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
        {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
        {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
        {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
    };

    参考:https://blog.csdn.net/qq_38293564/article/details/80432875

    10.notify()方法

    public final native void notify();

    该方法唤醒在该对象上等待的某个线程。

    11.notifyAll()方法

    public final native void notifyAll();

    该方法唤醒在该对象上等待的所有线程。

  • 相关阅读:
    scala list
    scala 数组 基本类型
    oracle 索引 。其中全文检索最变态
    友盟分享(微信分享,微博分享,Facebook分享)
    iOS文字描边
    字符串限制条件
    IOS开发之格式化日期时间
    动态获取Textfield输入的内容
    iOS 微信分享 朋友圈
    iPhone屏幕尺寸、分辨率及适配
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/10703649.html
Copyright © 2020-2023  润新知