「Java」Java的Object类

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战


Object类

所有类型都隐式的派生于Java.lang.Object类,其主要用于两个目的

  1. 使用Object引用绑定任何数据类型的对象
  2. Object类型执行许多基本的一般用途的方法,包括 equals(), finalize(), hashCode(), getClass(), toString(), notify(), notifyAll()和wait()等

底层执行

public class Object{

    private static native void registerNatives();
    static {
        registerNatives();
    }

}
复制代码

equals

equals不会改变==, ==依旧是比较地址


  public static void main(String[] args){

        Pie pie = new Pie();
        Pie pie1 = new Pie();
        System.out.println(pie == pie1);
    }

    static class Pie {
        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }
    
输出 false
复制代码

finalize

它的工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存


 public static void main(String[] args){

        Pie pie = new Pie();
        pie = null;
        System.gc();
    }

    static class Pie {

        @Override
        protected void finalize() throws Throwable {
            System.out.println("我要被回收了");
        }
    }
输出:我要被回收了
复制代码

hashcode

该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。

一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。


    public static void main(String[] args){

        Pie pie = new Pie();
        Pie pie1 = pie;
        Pie pie2 = new Pie();
        System.out.println(pie.hashCode() + " " + pie1.hashCode() + " " + pie2.hashCode());
    }

    static class Pie {
        @Override
        public int hashCode() {
            return super.hashCode();
        }
    }

输出:1163157884 1163157884 1956725890
复制代码

getClass

得到一个Class对象


    public static void main(String[] args){

        LittlePie littlePie = new LittlePie();
        System.out.println(littlePie.getClass());
        Class c = littlePie.getClass();
        Pie pie = null;
        try {
            pie = (Pie) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println(pie.getClass());
        System.out.println(littlePie instanceof LittlePie);
        System.out.println(pie instanceof LittlePie);
        System.out.println(littlePie instanceof Pie);
        System.out.println(littlePie instanceof Object);
    }

    static class Pie {
    }
    static class LittlePie extends Pie{

    }

输出:
class Main$LittlePie
class Main$LittlePie
true
true
true
true
复制代码

toString

toString返回一个字符串


    public static void main(String[] args){

        Pie pie = new Pie();
        System.out.println(pie.toString());
    }

    static class Pie {
        @Override
        public String toString() {
            return "i am pie->" + super.toString();
        }
    }

输出:i am pie->Main$Pie@4554617c
复制代码

notify, notifyAll, wait

wait,notify,notifyAll 是定义在Object类的实例方法,用于控制线程状态。

三个方法都必须在synchronized 同步关键字所限定的作用域中调用,否则会报错java.lang.IllegalMonitorStateException ,意思是因为没有同步,所以线程对对象锁的状态是不确定的,不能调用这些方法。

  • wait 表示持有对象锁的线程A准备释放对象锁权限,释放cpu资源并进入等待。
  • notify 表示持有对象锁的线程A准备释放对象锁权限,通知jvm唤醒某个竞争该对象锁的线程X。线程A synchronized 代码作用域结束后,线程X直接获得对象锁权限,其他竞争线程继续等待(即使线程X同步完毕,释放对象锁,其他竞争线程仍然等待,直至有新的notify ,notifyAll被调用)。
  • notifyAll 表示持有对象锁的线程A准备释放对象锁权限,通知jvm唤醒所有竞争该对象锁的线程,线程A synchronized 代码作用域结束后,jvm通过算法将对象锁权限指派给某个线程X,所有被唤醒的线程不再等待。线程X synchronized 代码作用域结束后,之前所有被唤醒的线程都有可能获得该对象锁权限,这个由JVM算法决定。

猜你喜欢

转载自juejin.im/post/7035284130459811848