Object类

Object类

什么是Object

Java中有一个比较特殊的类,就是 Object类,它是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承 Object类。因此,Object类是 Java 类层中的最高层类,是所有类的超类。换句话说,Java 中任何一个类都是它的子类。由于所有的类都是由 Object类衍生出来的,所以 Object类中的方法适用于所有类。

  1. public class Person //当没有指定父类时,会默认 Object 类为其父类
  2. {
  3. ...
  4. }

上面的程序等价于:

  1. public class Person extends Object
  2. {
  3. ...
  4. }

如果想引用你不知道的类型的对象,使用Object类是没有错的。请注意,父类引用变量可以引用子类对象,称为向上转换。下面举一个例子,有一个getObject()方法返回一个对象,但它可以是任何类型,如:EmployeeStudent等这样的类,我们可以使用Object类引用来引用该对象。 例如:

  1. Object obj=getObject();//we don't know what object will be returned from this method

Object类为所有对象提供了一些常见的行为,如对象可以进行比较,对象可以克隆,对象可以通知等。

Object类的方法

Object类提供了许多方法。 它们如下:

Object类的常用方法有: toString()equals()方法。

1.关于toString()方法

  • Object类里面定义toString()方法的时候返回的对象的哈希code码(对象地址字符串);

  • 可以通过重写toString()方法表示出对象的属性。

此方法是在打印对象时被调用的,下面有两个范例,一个是没复写toString()方法,另一个是复写了toString()方法,读者可比较两者的区别。

  1. package educoder;
  2. public class TestToStringDemo1 {
  3. public static void main(String[] args) {
  4. Person p = new Person();
  5. System.out.println(p);
  6. }
  7. }
  8. class Person extends Object {
  9. String name = "张三";
  10. int age = 18;
  11. }

输出结果:

educoder.Person@7852e922

从上面的程序中可以发现,在打印对象p的时候实际上打印出的是一些无序的字符串,这样的字符串很少有人能看懂什么意思,之后可以再观察下面的范例,下面的范例复写了Object类中的toString()方法。

  1. package educoder;
  2. public class TestToStringDemo2 {
  3. public static void main(String[] args) {
  4. Person p = new Person();
  5. System.out.println(p);
  6. }
  7. }
  8. class Person extends Object {
  9. String name = "张三";
  10. int age = 18;
  11. // 复写Object类中的toString()方法
  12. public String toString() {
  13. return "我是:" + this.name + ",今年:" + this.age + "岁";
  14. }
  15. }

输出结果:

我是:张三,今年:18岁

TestToStringDemo1.java程序相比,程序TestToStringDemo2.javaPerson

类中明确复写了 toString()方法,这样在打印对象p的时候,实际上是去调用了toString()方法,只是并没有明显的指明调用 toString()方法而已,此时第 6 行相当于:

  1. System.out.println(p.toString());

2.关于equals()方法

比较的是对象的引用是否指向同一块内存地址,一般情况下,比较两个对象时是比较它的值是否一致,那如何解决呢?思路也比较简单,重写equals()方法。

在不重写的情况下,我们先看下程序执行情况,创建两个相同类型的对象,并判断对象是否相等。

  1. package educoder;
  2. public class test {
  3. public static void main(String[] args) {
  4. Dog dog = new Dog();
  5. dog.name = "jack";
  6. Dog dog1 = new Dog();
  7. dog1.name = "jack";
  8. System.out.println(dog);
  9. System.out.println(dog1);
  10. if (dog.equals(dog1)) {
  11. System.out.println("两个对象是相同的");
  12. } else {
  13. System.out.println("两个对象是不相同的");
  14. }
  15. }
  16. }
  17. class Animal {
  18. }
  19. class Dog extends Animal {
  20. int age = 20;
  21. String name = "rose";
  22. public String toString() {
  23. return "Dog [age=" + age + ", name=" + name + "]";
  24. }
  25. }

输出结果:

Dog [age=20, name=jack]

Dog [age=20, name=jack]

两个对象是不相同的

分析下 : 两个对象分别new了一次,开辟了两个不同内存空间,内存地址不同。object提供的equals()是用来比较的是对象的引用是否指向同一块内存地址。很显然,内存地址不一样,所以是不相等的,跟属性值是否一样完全没有任何关系。

一般情况下,我们是需要判断对象的属性值相等的,那么如何重写 equals()方法呢?通过Eclipse(集成开发环境)提供的快捷键,Dog类中出现如下方法,方法的解释也放在代码中一并进行解释如下:

  1. package educoder;
  2. public class test {
  3. public static void main(String[] args) {
  4. Dog dog = new Dog();
  5. dog.name = "jack";
  6. Dog dog1 = new Dog();
  7. dog1.name = "jack";
  8. System.out.println(dog);
  9. System.out.println(dog1);
  10. if (dog.equals(dog1)) {
  11. System.out.println("两个对象是相同的");
  12. } else {
  13. System.out.println("两个对象是不相同的");
  14. }
  15. }
  16. }
  17. class Animal {
  18. }
  19. class Dog extends Animal {
  20. int age = 20;
  21. String name = "rose";
  22. public String toString() {
  23. return "Dog [age=" + age + ", name=" + name + "]";
  24. }
  25. /* getClass() 得到的是一个类对象 */
  26. @Override
  27. public boolean equals(Object obj) {
  28. if (this == obj)// 两个对象的引用是否相同,如果相同,说明两个对象就是同一个
  29. return true;
  30. if (obj == null)// 如果比较对象为空,不需要比较,肯定不相等
  31. return false;
  32. if (getClass() != obj.getClass())// 比较两个对象的类型是否相同,如果不同,肯定不相同
  33. return false;
  34. Dog other = (Dog) obj;// 转化成相同类型后,判断属性值是否相同
  35. if (name == null) {
  36. if (other.name != null)
  37. return false;
  38. } else if (!name.equals(other.name))
  39. return false;
  40. return true;
  41. }
  42. }

输出结果:

Dog [age=20, name=jack]

Dog [age=20, name=jack]

两个对象是相同的

equals()== 的区别:

  • 在Java中,任何类型的数据都可以用 “==”进行比较是不是相等,一般用于基本数据类型的比较,比较器存储的值是否相等。但是如果用于引用类型的比较,则是比较所指向对象的地址是否相等,在这点上,跟object类提供的equals()方法的作用是一致的。
  • 对于equals()方法

1) 首先,不能用于基本数据类型的变量之间的比较相等;

2) 如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;

3) 诸如StringDate等类都对equals方法进行了重写,比较的是所指向的对象的内容。

Java对象克隆

对象克隆是一种创建对象的精确副本的方法。Object类的clone()方法用于克隆对象。java.lang.Cloneable接口必须由我们要创建其对象克隆的类实现。如果我们不实现Cloneable接口,clone()方法将生成CloneNotSupportedException

clone()方法在Object类中定义。 clone()方法的语法如下:

  1. protected Object clone() throws CloneNotSupportedException

为什么要使用clone()方法?

clone()方法保存用于创建对象的精确副本的额外处理任务。 如果我们使用new关键字执行它,它将需要执行大量的处理,这就是为什么我们使用对象克隆。

对象克隆的优点:

  • 少处理任务。

clone()方法示例(对象克隆)

  1. package educoder;
  2. public class Student implements Cloneable {
  3. int rollno;
  4. String name;
  5. Student(int rollno, String name) {
  6. this.rollno = rollno;
  7. this.name = name;
  8. }
  9. public Object clone() throws CloneNotSupportedException {
  10. return super.clone();
  11. }
  12. public static void main(String args[]) {
  13. try {
  14. Student s1 = new Student(101, "amit");
  15. Student s2 = (Student) s1.clone();
  16. System.out.println(s1.rollno + " " + s1.name);
  17. System.out.println(s2.rollno + " " + s2.name);
  18. } catch (CloneNotSupportedException c) {
  19. }
  20. }
  21. }

输出结果:

101 amit

101 amit

从上面的例子可以看出,两个引用变量都有相同的值。 因此,clone()将对象的值复制到另一个对象。 因此,在实际应用中我们不需要编写显式代码将对象的值复制到另一个对象。如果通过new关键字创建另一个对象并将另一个对象的值赋给这个对象,则需要对该对象进行大量处理。 所以为了节省额外的处理任务,我们使用clone()方法。