10.9 Object类
万事万物皆对象。
Everything is object.
这是面向对象里面很著名的一句话,而Java把这句话贯彻到底:它定义了一个Object类(Object就是对象的意思),作为所有类的“祖先”类。根据继承的理论,所有类都是Object 类型!
java作为一个纯面向对象的语言,它有一个严格的继承体系,而这个体系的根,就是这个Object。也许有人会有疑问——自己定义的类呢,也是Object的子类吗?例如这样:
public class Tester{
}
其实就算是自定义的类,也是Object的子类,编译器会在类的后面加上继承关系:
public class Tester extends Object{
}
任意一个对象,都是Object对象,都可以类型转化成Object。
看下面代码的例子,ob是一个Object对象,test是一个String对象,同时它也是一个Object对象,所以这个赋值是合法的。
String test="Good!";
Object ob=test;
这里还是有例外的,那就是基本变量,例如int 、double这些,因为它们都不是类,所以并不是Object对象,为了统一,每个基本变量类型都有一种包装类与之对应。可参考9.4包装类。
int i=8;Object o=i;/** 实际上是 Object o=(Integer)i; */
Object里面有几个方法,任何类都可以复写它们。如果要适应所有的类,那么这些方法无疑是非常具有通用性,下面我们来看几个:
返回类型 | 方法名及参数 | 说明 | 示例 |
---|---|---|---|
boolean | equals(Object ob) | 比较当前对象和ob是否相等,两个对象是否相等,是和这个类的定义决定的,例如两个学生对象是否相等,可以判断这两个对象是否有相同的学号就可以了 | String类重写了这个方法,比较两个字符串内容是否相等 |
String | toString() | 返回一个表达这个对象的字符串 | 假设有一个复数类,那么可以复写这个toString方法,以a+bi的形式打印这个复数 |
Object | clone() | 克隆一个对象 | 这是另一个生成对象的方法,如果类提供了这个方法,那么可以通过它生成当前对象的复制品 |
Class | getClass() | 取得一个Class对象 | Class是一种记录此对象的方法和属性的一种类型 |
equals方法,我们在String类已经遇见过,事实上,String的equals就是复写了Object的equals,如果有这样的问题:需要比较某个类的对象是否相等,那么就需要复写这个方法。例如Stduent类,需要比较两个对象是否相等(是否是同一个学生):
public static void main(String[]args){ Student stu1=new Student(); stu1.name="John"; stu1.id="123456"; stu1.clazz="23计算机应用9班"; Student stu2=new Student(); stu2.name="John"; stu2.id="123456"; System.out.println(stu1.equals(stu2));}
这就有一个问题,stu1和stu2什么情况下才相等?这就需要Student的设计者来决定,于是Student类就需要重写equals方法。(通过eclipse的菜单的"源码"-》"覆盖和实现方法",再勾选Object类的equals方法,可以自动生成方法的框架)。下面的代码,Stduent类添加了equals方法,两个对象是否相等的条件是:它们的id和name属性不能为空;他们的id和name属性分别相等。
public class Student{ String name; String id; String clazz; public void printName(){ System.out.println("名字是:"+name); } public void setName(String name){ this.name=name; } @Override public boolean equals(Object obj){ Student stu=(Student)obj; if(stu.id==null || stu.name==null || this.id==null || this.name==null){ return false; } return this.id.equals(stu.id)&& this.name.equals(stu.name); } public static void main(String[]args){ Student stu1=new Student(); stu1.name="John"; stu1.id="123456"; stu1.clazz="23计算机应用9班"; Student stu2=new Student(); stu2.name="John"; stu2.id="123456"; System.out.println(stu1.equals(stu2)); }}
运行代码可见打印true,说明stu1和stu2是同一个学生。
String类就重写了equals方法,专门用来比较两个字符串的内容是否相等。
第二个方法toString,用来将对象转换成字符串。例如直接打印一个对象:
public class Student{ String name; String id; String clazz; public void printName(){ System.out.println("名字是:"+name); } public void setName(String name){ this.name=name; } @Override public boolean equals(Object obj){ Student stu=(Student)obj; if(stu.id==null || stu.name==null || this.id==null || this.name==null){ return false; } return this.id.equals(stu.id)&& this.name.equals(stu.name); } public static void main(String[]args){ Student stu=new Student(); stu.name="John"; stu.id="123456"; stu.clazz="23计算机应用9班"; System.out.println(stu); }}
直接运行代码,也就是打印stu对象,将会出现诸如“ccc.Student@15db9742”这样的输出,如果有把对象直接转化成字符串的需求,那么就要重写Object的toString方法:
public class Student{ String name; String id; String clazz; public void printName(){ System.out.println("名字是:"+name); } public void setName(String name){ this.name=name; } @Override public boolean equals(Object obj){ Student stu=(Student)obj; if(stu.id==null || stu.name==null || this.id==null || this.name==null){ return false; } return this.id.equals(stu.id)&& this.name.equals(stu.name); } @Override public String toString(){ StringBuffer buffer=new StringBuffer(); buffer.append("此学生的学号是").append(this.id).append(",姓名是").append(this.name).append(",班级是").append(this.clazz); return buffer.toString(); } public static void main(String[]args){ Student stu=new Student(); stu.name="John"; stu.id="123456"; stu.clazz="23计算机应用9班"; System.out.println(stu); }}
此时再打印Student对象,那么就会按照上面代码的toString方法来构建字符串打印。上面运行的输出是“此学生的学号是123456,姓名是John,班级是23计算机应用9班”
在eclipse里,也提供了方便的方法来继承父类的方法,我们就可以发现Object里面的所有可继承方法,随便找一个类,在代码区域右键点击鼠标,然后选择“源代码(source)”-> “覆盖/实现方法(Override/Implement Methods)”: