• Java核心技术第五章——2.Object类


    Object类:所有类的超类

    Object类是Java中所有类的始祖,在Java中每个类都是由它扩展而来的。但是并不需要这样写:

    public class Emloyee extends Object

    如果没有明确的指出超类,Object就被认为是这个类的超类。在Java中,只有基本数据类型不是对象,所有数组类型,不管是对象数组还是基本类型的数组都扩展(继承)了Object类。

    1.equals方法

    Object类中的equals方法用于检车一个对象是否等于另外一个对象。也就是说是否具有相同的引用。当时这种判断相同引用一般来说并没有什么luan用。一般只需要两个对象的状态相等,就认为这两个对象时相等的。

    public class Employee{
    
        private double salary;
    
        private LocalDate hireDay;
    
        public boolean equals(Object otherObject){
            if(this == otherObject) return true; //是否为相同引用
    
            if(otherObject==null) return false;
    
            if(this.getClass() != otherObject.getClass()) return false; //是否属于同一个类
    
            Employee other = (Employee)otherObject;//实例化同一个类则强转
            
            return salary==other.salary&&hireDay.equals(other.hireDay);//判断值是否一致。
        }
    
    }

    2.相等测试与继承

    Java语言规范要求equals方法具有下面的特性:

    1.自反性:对于任何非空引用x,x.equals(x)返回true

    2.对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true.

    3.传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true

    4.一致性:如果x和y引用的对象没有发生任何改变,返回调用x.equals(y)应该返回同样的结果。

    5.对于任何的非空引用x,x.equals(null)应该返回false。

    然而利用只getClass检测,是不符合置换原则的。这是因为没有任何一个子类需要重新定义集合是否相等的语义(重新定义equals方法)。在Object中的equals方法没有被声明为final,这样做,可以让子类选择更加有效的算法对集合进行是否相等的检测(重写equals方法)。

    如果子类能够拥有自己的相等概念(equals方法在子类中定义),则对称性需求将强制采用getClass进行检测。

    如果由超类决定相等的概念(equals方法在父类中定义),那么久可以使用instanceof进行检测。这样就可以在不同子类的对象之间进行相等的比较。(比较的域只能是父类的数据域)

    一个比较完善的equals方法:

    1.方法参数命名为otherObject 类型为Object,稍后用到。

    2.判断是否为同一引用,如果相同返回true。

    3.判断是否为Null,如果为Null则返回false;

    4.判断是否为同一个类或同一个父类,判断是否为同一个类时则需要在每个子类中定义equals方法(使用getClass方法判断)。

    如果判断是否为同一个父类,那么相等时只能使用到父类的equals方法(使用instanceof方法)。

    5.强制类型转换otherObject引用为需要判断的类型。

    6.判断基本数据类型域和对象域是否都一致。一致返回true.

    3.hashCode方法

    散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的。如果x和y是两个不同的对象,x.hashCode()和y.hashCode()基本上不会相同。例:

            String s = "OK";
            StringBuilder sb = new StringBuilder(s);
            System.out.println(s.hashCode() + "  " + sb.hashCode());
    
            String t = new String("OK");
            StringBuilder tb = new StringBuilder(t);
            System.out.println(t.hashCode() + "   " + tb.hashCode());
    2524  1376400422
    2524   418304857

    此处s和t拥有相同的散列码,这是因为字符串的散列码是由内容导出的。即内容相同,hashCode值相同。

    而StringBuffer类中没有定义hashCode方法,是因为它的散列码是由Object类的默认hashCode方法导出的对象存储地址。所以即对象不同,则hashCode值不同。

    注意:如果重新定义Equals方法后,hashCode也必须重新定义。保证x.equals(y)返回true,x.hashCode就必须和y.hashCode()的值一致。

    4.toString方法

    在Objcet中有一个重要的方法,就是toString方法,它用于返回表示对象值得字符串。而Objcet中的toString方法打印的是类名和散列码值。一般比较少用。

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

    而自定义的实体类,一般都会重写toString方法。而重写的toString方法用方括号把域值括起来。例:

        public String toString() {
            return getClass().getName()+"{" +
                    "salary=" + salary +
                    ", hireDay=" + hireDay +
                    '}';
        }

    如果是子类的程序员定义自己的toString方法,并将子域添加进去。那么子类增加super.toString即可。

    若类域包含数组类型的。那么使用toString方法将会把数组打印成类名@散列码。是因为数组继承了Object的toString方法。

    解决方法:一维数组使用Arrays.toString(数组引用),多维数组使用Arrays.deepToString(数组引用)。

    个人提倡使用lombok插件。不需要写set、get、toString方法。更详细的lombok插件解释请自行上网搜索。

    若小弟写的有什么不足之处,请在评论区评论或至邮箱821312534@qq.com。Thanks♪(・ω・)ノ

  • 相关阅读:
    leetcode-hard-array-454 4sum II-NO
    leetcode-hard-array-238. Product of Array Except Self-NO
    leetcode-hard-array-54. Spiral Matrix-NO
    leetcode-easy-trees-98. Validate Binary Search Tree-NO
    leetcode-easy-trees-108. Convert Sorted Array to Binary Search Tree
    leetcode-easy-trees-102. Binary Tree Level Order Traversal-YES
    leetcode-easy-trees-101. Symmetric Tree-YES
    leetcode-easy-trees-Maximum Depth of Binary Tree
    leetcode-easy-others-20 Valid Parentheses
    深度学习变革视觉计算总结(CCF-GAIR)
  • 原文地址:https://www.cnblogs.com/Johnson-lin/p/9404966.html
Copyright © 2020-2023  润新知