Java Object & Objects

231 阅读5分钟

Object

  • Object是Java中的顶级父类,所有的类都直接或间接地继承于Object类

  • Object类中的方法可以被所有子类访问,所以我们要学习Object类和其中的方法

Object的构造方法

方法名说明
public Object()空参构造

在继承中,子类中的共性才会被父类抽取,所以没有提供带参构造

Object的成员方法

方法名说明
public String toString()返回对象的字符串表示形式
public boolean equals(Object obj)比较两个对象是否相等
protected Object clone(int a)对象克隆

toString()

  • 字符串表示形式:
    • java.lang.Object@7875765
    • 包名+类名 @ 对象地址值
  • 细节:当使用println()方法直接打印对象时,获取的也是字符串表示形式
    • System.out.println();
      • System:类名
      • out:底层定义的一个静态变量public static final PrintStream out = null;
      • System.out:获取打印的对象
      • println():方法
      • 参数:打印的内容
    • 核心逻辑:当我们打印一个对象时,底层会调用对象的toString方法,把对象变成字符串,然后再打印再控制台上,打印完毕换行处理
  • 默认情况下,因为Object类中的toString方法返回的时地址值,所以再默认情况下,打印一个对象打印的就是地址值,但是地址值对我们来说时没什么意义的,我们更希望看到的是对象内部的属性值,这个时候就需要**重写父类Object类中的toString方法**

equals(Object obj)

  • 在Object底层中的equals方法原理是return this == obj;比较的是对象中的地址值,在对象的比较中意义不大,所以需要在子类中重写equals方法满足需求
String s = "abc";
StringBuilder sb = new StringBuilder("abc");
System.out.println(s.equals(sb));//false
System.out.println(sb.equals(s));//false
  • s.equals(sb)
    • 对象s是String类,看String类中的equals方法
    • String类中equals方法底层原理
      • 先判断参数是否为String类
      • 如果是String类,再比较内部的属性
      • 但如果参数不是String类,直接返回false
  • sb.equals(s)
    • 对象sb是StringBuilder类,看StringBuilder类中的equals方法
    • StringBuilder类继承于AbstractStringBuilder类,AbstractStringBuilder类默认继承于Object类
    • 而StringBuilder类和AbstractStringBuilder类中都没提供equals方法
    • 所以使用的是Object类中的equals方法,比较两个对象的地址值

clone(int a)

把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制

  • 无法直接调用clone方法

    • clone方法被protected修饰,只能在同一个包中、同一个包中的其他类、不同包下的子类被访问,而无法在不同包下的无关类中被访问,clone方法定义在java.lang包下
    • 因此想要使用clone方法只能自己去重写
  • 使用方式

    • 重写Object类中的clone方法
    @override
    protected Object clone() throws CloneNotSupportedException {
        //调用父类中的clone方法
        //相当于让java帮我们克隆一个对象,并把克隆之后的对象返回出去
        return super.clone();
    }
    
    • 让Javabean类实现Cloneable接口
      • 在Cloneable接口中没有抽象方法
      • 如果一个接口里面没有抽象方法
      • 表示当前接口是一个标记性接口
      • 现在Cloneable表示一旦实现了,那么当前类的对象就可被克隆
      • 如果没有实现,当前类的对象就不能克隆
    public class User implements Cloneable {
        
    }
    
    • 创建原对象并调用clone方法
      • Alt + Enter 选择第一个,让代码不要报错
      • clone方法返回的是一个Object对象,需要手动进行类型强转
    //方法会在底层帮我们创建一个对象,并把原对象中的数据拷贝过去
    User u2 = (User)u1.clone();
    

浅克隆

  • 不管对象内部的属性是基本数据类型还是引用数据类型,都拷贝过来
  • Object中的克隆是浅克隆

深克隆

  • 基本数据类型拷贝过来
  • 字符串复用
  • 引用数据类型会重新创建新的
  • 深克隆在clone方法中的实现方式:自己重写clone方法
@override
protected Object clone() throws CloneNotSupportedException {
	//先把被克隆对象中的数组取出来
    int[] data = this.data;
    //创建新数组
    int[] newData = new int[data.length];
    //拷贝数组中的数据
    for (int i = 0; i < data.length, i++) {
        newData[i] = data[i];
    }
    //调用父类中的方法克隆对象
    User u = (User) super.clone();
    //因为父类中的克隆方法是浅克隆,替换克隆出来对象中的数组地址值
    u.data = newData;
    return u;
}
  • 第三方工具类实现深克隆

    • 第三方写的代码导入到项目中
      • 当前模块下新建lib包
      • 将gson.jar复制到lib包中
      • 右键点击gson.jar,选择Add as library...,选择OK
    • 编写代码
    //创建对象
    Gson gson = new Gson();
    //把对象变成一个字符串
    String s = gson.toJson(u1);
    //再把字符串变回对象
    User user = gson.fromJson(s, User.claa);
    

Objects

Objects是一个工具类,提供了一些方法去完成一些功能

Objects的成员方法

方法名说明
public static bolean equals(Object a, Object b)先做非空判断,比较两个对象
public static boolean isNull(Object obj)判断对象是否为null,为null返回true,反之返回false
public static boolean nonNull(Object obj)判断对象是否为null,跟isNull的结果相反
  • Objects.equals方法底层原理
    • 先判断a和b是否为同一个对象,如果是,直接返回true
    • 再判断a是否为null,如果为null,直接返回false
    • 如果a不为null,那么就调用a中的equals方法
      • 如果类中重写了equals方法,比较属性值
      • 如果类中没有重写了equals方法,比较地址值
    • 解决了本类中equals方法当调用对象本身为null时遇到的空指针异常错误
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}
  • Objects.isNull方法底层原理
public static boolean isNull(Object obj) {
    return obj == null;
}
  • Objects.nonNull方法底层原理
public static boolean nonNull(Object obj) {
    return obj != null;
}