阿里云【名师课堂】Java面向对象开发75 ~ 78:Object类

75:Object类简介

Object是Java默认提供的一个类,可以说Java里面除了Object类之外,所有的类都是存在有继承关系的,默认会继承Object父类。
也就是说,以下两种类的定义格式产生效果是完全相同的。

class Message {
}
class Message extends Object {
}

那么也就证明,Object类可以接收所有类的对象。
范例:Object类接收对象

class Message {
}

class Person {
}

public class TestDemo {
	public static void main(String args[]) {
		method(new Message()) ;
		method(new Person()) ;
	}
	public static void method(Object obj) {
		System.out.println(obj) ;
	}
}

在这里插入图片描述
所以,在开发过程中,Object类是参数的最高统一类型。但是Object本身也具有一些定义的方法:

方法名称 类型 描述
public Object() 构造 无参构造专门为子类提供服务
public String toString() 普通 取得对象信息
public boolean equals(Object obj) 普通 对象的比较
  • 打开Java帮助文档,任意查看类,可以发现:Java所有类都是继承Object类
  • 回顾:所有类的子类对象的实例化都要调用父类中的构造方法,而Object是所有类的父类,因此Object中有public Object()构造方法。

76:取得对象信息

在使用对象直接输出的时候可以发现,默认情况下输出的是一个地址编码,比如75:Object类简介范例:Object类接收对象的输出结果:
在这里插入图片描述
而当使用String类的时候,输出的直接是内容。造成这种差异的原因是toString()方法。
范例:观察String类的输出

class Person {
	private String name ;
	private int age ;
	public Person(String name,int age) {
		this.name = name ;
		this.age = age ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		method("hello world") ; // String是Object类的子类,直接传入String类对象
		method(new Person("Dexter", 20)) ; // Person类自定义对象
	}
	public static void method(Object obj) {
		System.out.println(obj) ;
		System.out.println(obj.toString()) ;
	}
}

在这里插入图片描述
可以发现,默认输出对象obj调用的就是toString()方法。默认情况下,Object中的toString()方法只能够得到对象的地址(而且这是所有对象都共同具备的特征,因Object是所有类的子类)。


而现在如果觉得默认给出的toString()功能不足,就建议在需要的子类上覆写toString()方法。
范例:观察toString()的覆写

class Person {
	private String name ;
	private int age ;
	public Person(String name,int age) {
		this.name = name ;
		this.age = age ;
	}
	public String toString() { // 覆写Object类中的toString方法
		return "姓名:" + this.name + ",年龄:" + this.age ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		method("hello world") ; // String是Object类的子类
		method(new Person("Dexter", 20)) ; // 自定义对象
	}
	public static void method(Object obj) {
		System.out.println(obj) ; // 
		System.out.println(obj.toString()) ;
	}
}

在这里插入图片描述
所以说,toString()的核心目的在于取得对象信息。相当于替换了之前简单Java类中的getInfo()方法。
提醒:String是作为信息输出的重要的数据类型。在Java中,所有的数据类型只要遇见String,并且执行了+这种功能连接操作,那么都会变为字符串后连接。而所有对象要想变为字符串就默认使用toString()方法。
范例:观察对象变为字符串

class Person() {······}

public class TestDemo {
	public static void main(String args[]) {
		String str = "hello," + new Person("Dexter", 20) ; // 这里的对象自动调用重载的toString方法,变为了字符串
		System.out.println(str) ; // 自定义对象
	}
}

在这里插入图片描述

77:对象比较

String类内容的比较使用的是equals()方法,实际上这个equals()方法就是String类覆写的Object类的方法。
观察:

  • Object类中的equals()方法:
    • public boolean equals(Object obj)
  • String类中的equals()方法:
    • public boolean equals(String anObject)

以后需要进行对象比较时,可以通过覆写equals()方法实现需求的功能,取代compareTo()等方法。


范例:实现对象比较

class Person {
	private String name ;
	private int age ;
	public Person(String name,int age) {
		this.name = name ;
		this.age = age ;
	}
	
	public boolean equals(Object anObject) {
		if (anObject == null) {
			return false ;
		}
		if (this == anObject) { // 传入equals的对象(anObject)等于调用equals的对象(this)
			return true ; // 不用进行比较,因为自己等于自己
		}
		// 但是父类(Object)并不知道子类(String)中有什么属性,需要下转型才可以调用name、age
		Person per = (Person)anObject ;
		return this.name.equals(per.name) && this.age == per.age ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Person per1 = new Person("Dexter", 20) ;
		Person per2 = new Person("Dexter", 20) ;
		System.out.println(per1.equals(null)) ;
		System.out.println(per1.equals(per1)) ;
		System.out.println(per1.equals(per2)) ;
	}
}

在这里插入图片描述


这时新的问题出现了:anObject被下转型为Person类的对象,这时如果参与比较的不是Person类的对象(比如per1.equals("HELLO"))就会报错:ClassCastException。
因此,需要在传入的对象进行比较前判断传入对象属于哪个类:

class Person {
······
	
	public boolean equals(Object anObject) {
		if (anObject == null) {
			return false ;
		}
		if (this == anObject) { // 传入equals的对象(anObject)等于调用equals的对象(this)
			return true ; // 不用进行比较,因为自己等于自己
		}
		if (!(anObject instanceof Person)) { // 判断传入对象是否是Person类的对象
			return false ;
		}
		// 但是父类(Object)并不知道子类(String)中有什么属性,需要下转型才可以调用name、age
		Person per = (Person)anObject ;
		return this.name.equals(per.name) && this.age == per.age ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		Person per1 = new Person("Dexter", 20) ;
		System.out.println(per1.equals("HELLO")) ;
	}
}

在这里插入图片描述


这时又有新问题出现了:
可不可以用public boolean equals(Person anObject) {}直接判断传入的对象是否是Person类对象呢?

  • 不可以。因为父类的equals()方法在传入对象时用的是Object,这时把它换为Person,这个操作已经不再是覆写,而是方法重载,因为参数类型不同了。

78:接收引用数据类型

之前已经分析了,Object可以接收任意的对象,因为从定义的结构上来讲,Object是所有类的父类。
但是Object的概念不止于此,它可以接收所有的引用数据类型:数组、接口、类。

  • 所有使用Object接收的都是向上转型

接收数组

范例:使用Object接收数组对象

public class TestDemo {
	public static void main(String args[]) {
		// 利用Object类接受数组对象,这里数组自动上转型
		Object obj = new int [] {1, 2, 3} ;
		// 所以还要强制下转型
		int[] data = (int[])obj ;
		for (int i = 0 ; i < data.length ; i++) {
			System.out.print(data[i] + "、") ;
		}
	}
}

在这里插入图片描述

接收接口

interface IMessage {
}

class MessageImpl implements IMessage {
	public String toString() { // toString是Object类的方法
		return "hello world" ;
	}
}

public class TestDemo {
	public static void main(String args[]) {
		IMessage msg = new MessageImpl() ; // 子类向父接口转型
		Object obj = msg ; // 接口向Object转型
		System.out.println(obj) ; //调用被覆写的toString()方法
	}
}

通过76:取得对象信息中的几道范例程序我们可以知道,System.out.println(obj) ;就等于System.out.println(obj.toString) ;,因为Java使用 System.out.println()方法直接输出对象时,或者把某个对象和字符串进行连接运算时,系统会自动调用该对象的toString()方法返回该对象的字符串表示。

猜你喜欢

转载自www.cnblogs.com/playerone/p/13166765.html