Object类

java.lang.Object类所有类的根类,每个类都将Object作为超类,所有类的对象,包括数组都实现这个类的方法。常用的方法:

  • String toString():返回对象的字符串表示。假设Person定义如下所示,它默认继承了Object这个超类:

    1. public class Person {
    2. private String name;
    3. private int age;
    4. public Person() {
    5. }
    6. public Person(String name, int age) {
    7. this.name = name;
    8. this.age = age;
    9. }
    10. public String getName() {
    11. return name;
    12. }
    13. public void setName(String name) {
    14. this.name = name;
    15. }
    16. public int getAge() {
    17. return age;
    18. }
    19. public void setAge(int age) {
    20. this.age = age;
    21. }
    22. }

  • 如果我们直接使用toString方法来输出对象调用toString方法的结果,最后得到的对象的地址值,本质上和直接输出对象自己没有区别。

    public class ObjectMain {
      public static void main(String[] args) {
          Person person = new Person("Forlogen", 18);
          System.out.println(person); // Object.Person@1b6d3586
    
          // 直接打印对象的名字本质上就是调用了对象的toString方法
          String s = person.toString();
          System.out.println(s); // Object.Person@1b6d3586
    

  • 所以,为了更加是toString符合具体的应用场景,我们需要重写toString方法,在IDEA中使用自动生成得到:

      @Override
      public String toString() {
          return "Person{" +
                  "name='" + name + '\'' +
                  ", age=" + age +
                  '}';
      }
    

  • 如上所示,通过重写方法最后得到的是类的成员变量信息而不是对象的地址值。那么,我们再看一些Java内置的其他类是否也重写了toString方法:

    Random r = new Random();
    System.out.println(r);  // java.util.Random@74a14482
    

  • 从输出结果可以看出,Random并没有重写toString方法。

    // 重写了toString
    Scanner sc = new Scanner(System.in);
    System.out.println(sc);  // java.util.Scanner[delimiters=\p{javaWhitespace}+][position=0] ...
    

  • 从输出结果可以看出,Scanner类重写了toString方法,我们通过源码看一下具体的重写过程:

      /**
       * <p>Returns the string representation of this <code>Scanner</code>. The
       * string representation of a <code>Scanner</code> contains information
       * that may be useful for debugging. The exact format is unspecified.
       *
       * @return  The string representation of this scanner
       */
      public String toString() {
          StringBuilder sb = new StringBuilder();
          sb.append("java.util.Scanner");
          sb.append("[delimiters=" + delimPattern + "]");
          sb.append("[position=" + position + "]");
          sb.append("[match valid=" + matchValid + "]");
          sb.append("[need input=" + needInput + "]");
          sb.append("[source closed=" + sourceClosed + "]");
          sb.append("[skipped=" + skipped + "]");
          sb.append("[group separator=" + groupSeparator + "]");
          sb.append("[decimal separator=" + decimalSeparator + "]");
          sb.append("[positive prefix=" + positivePrefix + "]");
          sb.append("[negative prefix=" + negativePrefix + "]");
          sb.append("[positive suffix=" + positiveSuffix + "]");
          sb.append("[negative suffix=" + negativeSuffix + "]");
          sb.append("[NaN string=" + nanString + "]");
          sb.append("[infinity string=" + infinityString + "]");
          return sb.toString();
      }
    

  • 重写过程中使用了StringBuilder来保存输出的结果,最后使用StringBuilder中的toString方法输出字符串。

    ArrayList<String> list = new ArrayList<>();
    list.add("Forlogen");
    list.add("kobe");
    System.out.println(list);  // [Forlogen, kobe]
    

  • 可以看到ArrayList也重写了toString方法,但是在ArrayList的实现中并没有自己重写toString,而ArrayList继承了java.util包下的AbstractCollention类,该类中进行了toString方法的重写。

      /**
       * Returns a string representation of this collection.  The string
       * representation consists of a list of the collection's elements in the
       * order they are returned by its iterator, enclosed in square brackets
       * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
       * <tt>", "</tt> (comma and space).  Elements are converted to strings as
       * by {@link String#valueOf(Object)}.
       *
       * @return a string representation of this collection
       */
      public String toString() {
          Iterator<E> it = iterator();
          if (! it.hasNext())
              return "[]";
    
          StringBuilder sb = new StringBuilder();
          sb.append('[');
          for (;;) {
              E e = it.next();
              sb.append(e == this ? "(this Collection)" : e);
              if (! it.hasNext())
                  return sb.append(']').toString();
              sb.append(',').append(' ');
          }
      }
    

  • 重写的过程和Scanner是类似的。

  • boolean equals(Object obj):指示其他某个对象是否和此对象相等,Object类中的equals方法实现代码为:

    public boolean equals(Object obj) {
      return (this == obj);
    }
    

  • 它实现了本身和传入的对象的对比。我们知道 == 对于引用类型来说,进行的是地址值的比较,所以如果不是两个完全相同的对象,那么得到的就是false。

    public class ObjectEquals {
      public static void main(String[] args) {
          Person person = new Person("Forlogen", 18);
          Person person1 = new Person("kobe", 24);
          System.out.println(person.equals(person1));  // false
      }
    }
    

  • 同样为了具体的应用场景,通常需要重写equals方法:

    @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (!(o instanceof Person)) return false;
          Person person = (Person) o;
          return getAge() == person.getAge() &&
                  Objects.equals(getName(), person.getName());
      }
    
      @Override
      public int hashCode() {
          return Objects.hash(getName(), getAge());
      }
    

  • Java内置的其它类中很多也重写了equals方法,如String中就进行了equals方法:

    /**
       * Compares this string to the specified object.  The result is {@code
       * true} if and only if the argument is not {@code null} and is a {@code
       * String} object that represents the same sequence of characters as this
       * object.
       *
       * @param  anObject
       *         The object to compare this {@code String} against
       *
       * @return  {@code true} if the given object represents a {@code String}
       *          equivalent to this string, {@code false} otherwise
       *
       * @see  #compareTo(String)
       * @see  #equalsIgnoreCase(String)
       */
      public boolean equals(Object anObject) {
          if (this == anObject) {
              return true;
          }
          if (anObject instanceof String) {
              String anotherString = (String)anObject;
              int n = value.length;
              if (n == anotherString.value.length) {
                  char v1[] = value;
                  char v2[] = anotherString.value;
                  int i = 0;
                  while (n-- != 0) {
                      if (v1[i] != v2[i])
                          return false;
                      i++;
                  }
                  return true;
              }
          }
          return false;
      }
    

  • 通过对象直接调用

    public class ObjectEquals {
      public static void main(String[] args) {
          String s1 = "abc";
          String s2 = "abc";
    
          System.out.println(s1.equals(s2)); // true
      }
    }
    

    通常为了避免使用equals方法出现空指针异常,可以使用Objects的equals方法:

public class ObjectEquals {
 public static void main(String[] args) {
     String s1 = null;
     String s2 = "abc";

     System.out.println(s1.equals(s2)); // 会出现空指针异常
     System.out.println(Objects.equals(s1, s2));  // false
 }
}

java中的Object类 java.lang包【Object类】