第17篇:Java 的基类(Object 类)的方法介绍

简介: 🌻 【==】① 应用于基本类型的时候,是判断值是否相等② 应用于引用类型的时候,是判断对象的地址值是否相等(即判断两个对象的引用指向的是否是同一个对象)

一、前言

🌻 类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现Object 类的方法。

二、equals() 和【==】

(1) ==

🌻 【==】

  • ① 应用于基本类型的时候,是判断是否相等
  • ② 应用于引用类型的时候,是判断对象的地址值是否相等(即判断两个对象的引用指向的是否是同一个对象)

仔细分析下面的代码, 思考打印结果:

class Animal {

}

class Cat extends Animal {
    public String name = "卡菲猫";
    public int age = 3;
}

public class TestDemo {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Animal animal = returnObj(cat);

        System.out.println(cat == animal); // true
        System.out.println(cat.age == 3); // true
        System.out.println(cat.age == 33); // false
    }

    private static Animal returnObj(Animal animal) {
        if (animal instanceof Cat) return animal;
        return null;
    }
}

(2) equals

🌻 equals()
① 是Object类中的方法,只能判断引用类型的地址是否相等
② 默认判断的是地址是否相等,子类往往重写该方法以判断内容是否相等(如:Integer、String)
在这里插入图片描述

class Animal {
}

class Cat extends Animal {
}

public class TestDemo {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Animal animal = returnObj(cat);

        // 判断两个对象的引用指向的是否是同一个对象
        System.out.println(cat.equals(animal)); // true

    }

    private static Animal returnObj(Animal animal) {
        if (animal instanceof Cat) return animal;
        return null;
    }
}

(3) 比较两个字符数组的内容是否一样

🌻 编写代码:判断两个给定字符数组的内容是否一样【一样返回 true,否则返回 false

public class TestDemo {
    public static void main(String[] args) {
        char[] a = "desert".toCharArray();
        char[] b = "dessert".toCharArray();
        System.out.println(isEqualCharArr(a, b)); // false

        a = "new Handsome()".toCharArray();
        b = a;
        System.out.println(isEqualCharArr(a, b)); // true
    }

    private static boolean isEqualCharArr(char[] c1, char[] c2) {
        if (c1 == null || c2 == null) return false;
        int c1Len = c1.length;
        int c2Len = c2.length;

        // 两个字符数组的长度不一样
        if (c1Len != c2Len) return false;

        int i = 0; // 从第 0 位开始比较
        // 一共要比较 c1Len 次数
        // 比较一次后, 把 c1Len 的值减1
        while (c1Len-- != 0) {
            // 基本类型直接通过【!=】进行判断
            if (c1[i] != c2[i]) {
                return false;
            }
            i++;
        }
        return true;
    }
}
🎈 遍历两个字符数组,然后挨个比较即可
🎈 这里通过 while 语句进行循环,是为了下一节能够更加容易地看明白【String 类重写 Object 类的 equals 方法的代码】

(4) String 类重写 equals

🌼 String 类重写 equals 方法,用于判断是否相等
String 类重写 equals 的代码:

  public boolean equals(Object anObject) {
        // 判断传入参数和当前对象的地址值是否一样
        // 如果一样, 直接返回 true, 不执行下面的代码
      if (this == anObject) {
          return true;
      }
      // 如果传入的参数是 String 类型或 String 类型的子类型
      if (anObject instanceof String) {
          // 把传入的参数向下转型为 String 类型
          String anotherString = (String)anObject;
          // 拿到当前对象的 value 的长度
          // value 是 String 类中存储字符的数组(可看下面的图片)
          int n = value.length;
          // 拿到传入的参数的 value 的长度
          // 并和当前对象的 value 的长度比较
          // 若长度一样, 才执行 if 语句代码块的内容
          if (n == anotherString.value.length) {
              // v1 指向当前对象的 value(存储字符的数组)
              char v1[] = value;
              // v2 指向参数对象的 value(存储字符的数组)
              char v2[] = anotherString.value; 
              int i = 0; // 从第 0 个字符开始比较
              // 一共循环 n 次(比较 n 次)
              // 每比较完一次, n 的值减少 1
              while (n-- != 0) {
                    // v1 数组和 v2 数组有一个字符不一样
                  if (v1[i] != v2[i])
                      return false;
                  i++; // 以便于比较下一个字符
              }
              return true;
          }
      }
      // 以下两种情况都会执行下面的【return false;】语句
      // 1.传入的参数不是 String 类型或 String 类型的子类型
      // 2.当前对象的长度和传入的参数的长度不一样
      return false;
  }

在这里插入图片描述


public class TestDemo {
    public static void main(String[] args) {
        String s1 = "good";
        // true
        System.out.println(s1.equals(returnStr(1)));
        // false
        System.out.println(s1.equals(returnStr(0)));
        // false
        System.out.println(s1.equals(returnStr(2)));
    }

    private static String returnStr(int idx) {
        String[] strings = {"hello", "good", "morning"};
        return strings[idx];
    }
}

(5) Integer 类重写 equals

🌼 Integer 类重写 equals 方法,用于判断是否相等。
在这里插入图片描述


(6) Exercise

① 编程题

🌼 【判断两个 Person 对象的内容是否相等】若两个 Person 对象的每个属性值都一样,则返回true,否则返回false

☘️ 重写 equals方法,在方法体中判断属性值是否一样
public class Person {
    private String name;
    private int age;
    private char gender;

    public Person(String name, int age, char gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    /**
     * 重写 Object 的 equals 方法
     *
     * @param obj 待比较对象
     * @return obj 和当前对象的属性的值是否是一样的?一样:true; 不一样: false
     */
    @Override
    public boolean equals(Object obj) {
        // 如果 obj 为 null, 直接返回 false
        if (obj == null) return false;
        // 如果 obj 不属于 Person 类型, 直接返回 false
        if (!(obj instanceof Person)) return false;
        // 如果 obj 指向的对象就是当前对象(this), 直接返回true
        if (this == obj) return true;

        /* 判断 obj 的属性和当前对象的属性的值是否相等 */
        Person objPerson = (Person) obj; // 向下转型(强制类型转换为 Person 类型)
        return (objPerson.name.equals(this.name)) &&
                (objPerson.age == this.age) &&
                (objPerson.gender == this.gender);
    }
}

class TestDemo {
    public static void main(String[] args) {
        Person zhn = new Person("张浩男", 12, '男');
        Person qy = new Person("庆医", 1, '男');
        Person zgq = new Person("庆医", 1, '男');
        Person hn = zhn;

        System.out.println(zhn.equals(qy)); // false
        System.out.println(qy.equals(new StringBuilder())); // false
        System.out.println(zgq.equals(qy)); // true
        System.out.println(zhn.equals(hn)); // true
        System.out.println(qy.equals(null)); // false
    }
}

② 输出的结果是什么?

看下面的代码,思考输出的结果是什么?

public class Person {
    public String name;
}

class TestDemo {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "愿万事顺心";

        Person p2 = new Person();
        p2.name = "愿万事顺心";

        // 【==】应用于对象:判断地址值是否相等
        System.out.println(p1 == p2); // false

        // String 重写了 Object 的 equals, 用于判断值是否相等
        System.out.println(p1.name.equals(p2.name)); // true

        // p1 和 p2 指向的肯定不是同一个对象
        // 只要是【new】出来的都是在堆空间开辟了内存的
        System.out.println(p1.equals(p2)); // false

        String s1 = new String("Hello Boy!");
        // s2 的写法就类似 s1 的写法
        String s2 = "Hello Boy!";

        System.out.println(s1.equals(s2)); // true
        System.out.println(s1 == s2); // false
    }
}

③ 输出的结果是什么?

看下面的代码,思考输出的结果是什么?

class TestDemo {
    public static void main(String[] args) {
        int i = 65;
        float f = 65.0F;
        System.out.println(i == f); // true

        char c1 = 'A';
        char c2 = 12;
        System.out.println(i == c1); // true
        System.out.println(c2 == 12); // true

        String s1 = new String("HELLO");
        String s2 = new String("HELLO");
        System.out.println(s1 == s2); // false 
        System.out.println(s1.equals(s2)); // true
    }
}

三、hashCode()

🌻 hashCode():返回当前对象的哈希值
🌻 hashCode()方法作用:提高哈希表(如java.util.Hashtable 包提供的哈希表)的性能。
🌻 若两个引用指向的是同一对象,则哈希值肯定是一样的(反之,如果指向的不是同一个对象,则哈希值肯定不一样)
🌻 哈希值是根据对象的地址值计算出来的,可以用哈希值唯一标识一个对象。但哈希值和对象的地址值是完全不同的东西。

public class TestDemo {
    public static void main(String[] args) {
        Apple a1 = new Apple();
        Apple a2 = new Apple();
        Apple a = a1;
        /*
            a1 和 a2 指向的不是同一个对象(a1 和 a2 的哈希值肯定不一样)
            a 和 a1 指向的是同一个对象(a 和 a1 的哈希值是一样的)
         */
        System.out.println("a.hashCode(): " + a.hashCode());
        System.out.println("a1.hashCode(): " + a1.hashCode());
        System.out.println("a2.hashCode(): " + a2.hashCode());
    }
}

class Apple {
}

在这里插入图片描述
上图输出的哈希值是十进制的


四、toString()

🌻 返回该对象的字符串表示
🌻 toString()会返回一个【以文本形式表示】此对象的字符串。结果应是一个简明但易于读懂的信息表达式
🌻 直接打印对象(对象的引用)默认就是调用该对象的toString()
🌻 Object 类的 toString()会返回一个字符串

☘️ 字符串的格式是:全类名 + @符号 + 该对象哈希值的无符号十六进制表示
getClass().getName() + "@" + Integer.toHexString(hashCode())
public class TestDemo {
    public static void main(String[] args) {
        Apple apple = new Apple();
        // com.gq.Apple@1540e19d
        System.out.println("\n" + apple.toString());

        // 直接打印对象(对象的引用)默认就是调用该对象的 toString()
        // com.gq.Apple@1540e19d
        /*
            全类名:com.gq.Apple
            @符号:@
            哈希值的无符号十六进制表示:1540e19d
         */
        System.out.println("\n" + apple);

        /* toString() 返回的字符串的格式 */
        String hashCode = apple.getClass().getName() +
                "@" +
                Integer.toHexString(apple.hashCode());
        // com.gq.Apple@1540e19d
        System.out.println(hashCode);
    }
}

class Apple {
}

在这里插入图片描述

五、finalize()

🌻 当垃圾回收器Garbage Collector)确定不存在对该对象的更多引用时,由对象的垃圾回收器调用finalize()方法

🌻 对象被回收的时候(对象没有被任何指针指向的时候),gc(垃圾回收器)会调用finalize()方法

☘️ 当某个对象没有被任何指针引用的时候,Java 虚拟机就认为该对象是一个垃圾对象。就会使用垃圾回收机制来销毁该对象,在修改该对象前会先调用 finalize()方法
☘️ 垃圾回收机制的调用是由 JVM 决定的,也可通过 System.gc()触发垃圾回收机制【但即使主动调用垃圾回收器也不一定调用成功】

🌻 子类可重写finalize()方法,做一些资源释放的操作

public class TestDemo {
    public static void main(String[] args) {
        Car car = new Car();
        car = null;

        /* 触发垃圾回收机制 */
        System.gc();
    }
}

class Car {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("\nCar_finalize()");
        System.out.println("释放了数据库连接\n");
    }
}

在这里插入图片描述

结束!若有错误,请不吝赐教!

相关文章
|
15天前
|
Java
Java中ReentrantLock中tryLock()方法加锁分析
Java中ReentrantLock中tryLock()方法加锁分析
13 0
|
4天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
29 3
|
1天前
|
Java
Java 与垃圾回收有关的方法
Java 与垃圾回收有关的方法
|
1天前
|
安全 Java 程序员
|
2天前
|
存储 Java 测试技术
一文搞清楚Java中的方法、常量、变量、参数
在JVM的运转中,承载的是数据,而数据的一种变现形式就是“量”,量分为:**常量与变量**,我们在数学和物理学中已经接触过变量的概念了,在Java中的变量就是在程序运行过程中可以改变其值的量。
9 0
|
2天前
|
XML JSON Java
作为所有类的顶层父类,没想到Object的魔力如此之大!
在上一篇博文中我们提到了Java面向对象的四大特性,其中谈及“抽象”特性时做了一个引子,引出今天的主人公Object,作为所有类的顶级父类,Object被视为是James.Gosling的哲学思考,它高度概括了事务的自然与社会行为。
45 13
|
2天前
|
Java
Java Class类
Java Class类
8 0
|
6天前
|
存储 Java
Java动态转发代理IP的实现方法
Java动态转发代理IP的实现方法
22 11
|
7天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
14 0
Java接口中可以定义哪些方法?
|
9天前
|
Java 编译器
Java Character 类
4月更文挑战第13天