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 插件解释请自行上网搜索.
来源: https://www.cnblogs.com/Johnson-lin/p/9404966.html