------- android培训、java培训、期待与您交流! ----------
1. Object类简介
在Java的API文档中是这么介绍Object类的:Object类是类层次结构的根类,每个类都是Object类的子类。因此,我们在定义一个新类的时候,类名后面总会默认的添加了“extends Object”。也就是说,在创建对象的过程中,子类构造函数总会默认地访问到Object类的构造函数,而且Object类中定义的是所有类中具备的共性方法。
2. Object类方法简介
1) 比较相等——equals()
(a) 比较地址值
代码1:
//简单定义一个Demo类
class Demo{}
class ObjectDemo
{
public static void main(String[] args)
{
//创建两个Demo对象
Demo d1 = new Demo();
Demo d2 = new Demo();
//打印两个Demo对象的比较值
System.out.println(d1.equals(d2));
//将d1引用的值赋给d3引用,这样d1和d3就都指向了堆内存中的同一片内存
//换句话说,指向了同一个对象
Demo d3 = d1;
System.out.println(d1.equals(d3));
}
}
运行结果为:
false
true
实际上,equals方法比较的是两个对象在堆内存中的地址值。那么由于d1和d2两个引用指向了两个不同的对象,所对应的地址值必然是不同的;而d1和d3指向同一个对象,地址值当然也就相同了。
通过查阅API文档可知,equals方法的参数列表是:Object obj。也就是说,无论我们后期定义什么样的新类,因为都默认是Object类的子类,所以都可以通过多态方式将对象传入,比较两个对象的地址值,因此该方法的扩展性很好。
(b) 复写equals方法
在实际开发中,我们常常需要通过比较两个对象的属性以判断两者是否相同,仅仅比较地址值是不够的。这时候就需要在新类中通过复写的方式,重新定义Object类中的equals方法。这里我们以Person类为例,比较两对象的age属性来判断两者是否相同。
代码2:
class Person
{
private int age;
Person(intage)
{
this.ag e= age;
}
public int getAge()
{
return age;
}
/*
复写了Object类中的equals方法
首先判断传入的对象是否是Person类型
如果不是Person类型,直接返回false
反之,就将其强转为Person类
最后,通过比较两个Person对象(本类对象和传入对象)的age成员变量值
来判断两个对象是否相同
*/
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;//专业做法因为抛出异常,后面会详细讲解。
Person p = (Person)obj;
return age == p.getAge();
}
}
class ObjectDemo2
{
public static void main(String[] args)
{
Person p1 = new Person(20);
Person p2 = new Person(24);
System.out.println(p1.equals(p2));
}
}
运行结果为:
false
在上述equals方法中进行了if语句的判断。这样做的目的是防止向equals方法中传入非Person类对象后造成的类型转换异常。只有经判断确认传入对象是Person类以后,再进行强转动作。这样做提高了代码健壮性。
2) 打印对象——toString()
toString,顾名思义,是将对象转换成字符串。换句话说,对象中toString方法会返回一个字符串,我们通过一个简单的演示看看返回什么字符串:
代码3:
class Demo{}
class ObjectDemo2
{
public static void main(String[] args)
{
Demo d = new Demo();
System.out.println(d.toString());
}
}
运行结果为:
Demo@ac6a45
API文档中对该方法的描述是这样的:Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
getClass().getName() + '@' +Integer.toHexString(hashCode())
关于上述代码的解释如下:
getClass:这个方法会返回一个Class类型的“类文件对象”。所谓Class类就是对每个类对应的xxx.class文件(字节码文件,下同)的描述。由于这些字节码文件都是一些比较复杂的事物,包含了类名、构造方法、一般方法等信息,就像其他事物一样,我们就应该将复杂的事物封装成类进行描述。我们在回过头来说getClass方法,那么对象通过调用这个方法将该对象对应的类文件对象返回来了。
hashCode:返回该对象对应的整型哈希值。关于哈希值后面会有详细说明,大家可以简单那理解为对象在堆内存中的地址值(实际上并不是)。
Class<T>.getName:类文件对象通过调用getName方法就可以获取该对象(由类创建的对象,而不是类文件对象)对应类的名称(以字符串的形式)。
Integer.toHexString:通过Integer类的静态方法toHexString,返回某个整型10进制数对应的16进制数的字符串形式。
通过上述四个方法,并在中间添加一个字符串“@”,就是Object类默认的toString方法的返回结果。
小知识点1:
Class类中还定义了名为getMethods的方法,可以通过该方法获取到某个字节码文件中定义的所有方法,包括私有方法。这个动作我们可以称之为反编译,意思就是通过Java的运行文件(字节码文件),可以推测出这个字节码文件中的代码。
除此之外,API文档中还有这样的提示:toString 方法返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。也就是说,通过上述代码返回的字符串没有什么太大的实际意义。我们可以通过返回该对象内部封装的特有数据(属性),来对该对象进行描述。比如,以Person类为例,可以通过toString方法返回,姓名、年龄等信息,这样更为直观易于理解。