14、Object类
Object类 是类层次结构的跟类
每个类都是用Object作为超类。所有对象(包括数组)都实现这个类的方法。
所有类都是Object类的子类。
public String toString()方法:返回该对象的字符串表示。
通常,toString方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明且易于读懂的信息表达式。建议所有子类都重写此方法。
public boolean equals(Objects obj)方法:指示其他某个对象是否与此对象“相等”。equals方法在非空对象引用上实现相等关系:
自反性:对于任何非空引用值x,x.equals(x)都行返回true。
对称性:对于任何非空引用值x、y,当且仅当y.equals(x)返回true时,x.equals(y)返回true。
传递性:对于任何非空引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true时,那么x.equals(z)就返回true。
一致性:对于任何非空引用值x、y,多次调用x.equals(y)返回true或返回false,前提是对象上equals比较中所用的信息没有被修改。
对于任何非空引用值x,x.equals(null)都应返回false(因为既然有:x.equals(null),就一定能说明x非空)。
public class Demo1
{
public static void main(String[] args)
{
Student s = new Student();
System.out.println(s.toString());
}
}
class Student
{
private String name;
private int sid;
private int age;
public Student(){}
public Student(int sid, String name, int age)
{
this.sid = sid;
this.name = name;
this.age = age;
}
}
/*其实这个时候Student是一个类的子类,其父类是Object类。其结果为:
Student@7852e922
*/
我们可以看到,在下面的类中,没有toString()的方法,怎么会输出toString()呢?我们打开jdk1.8.0_192\java\lang\,打开Object.java,在里面找到有这样的代码(我这个代码是在235行):
来分析一下这段代码,它返回的是getName,指的是我们创建的子类(Student)名,中间输出一个@,后面输出的是一串数字字母组合的代码。Hex:16进制。所以现在我们都不懂这个信息,所以建议所有子类都重写此方法(此方法:toString()方法)。
我们把上面我写的类中的代码改一下,在类里面添加toString()方法:
public class Demo1
{
public static void main(String[] args)
{
Student s = new Student(1, "飞飞", 18);
System.out.println(s.toString());
}
}
class Student
{
private String name;
private int sid;
private int age;
public Student(){}
public Student(int sid, String name, int age)
{
this.sid = sid;
this.name = name;
this.age = age;
}
public String toString() //这个是把父类的toString方法重写了,返回的是学号、名字、年龄
{
return "SID = "+sid+", Name = "+name+", Age = "+age;
}
}
/*
结果:
SID = 1, Name = 飞飞, Age = 18
*/
当然我们在主函数输出语句中把s.toString()改成s,它会默认输出的,还是SID = 1, Name = 飞飞, Age = 18.
我们再看Object类的equals方法:
首先自反性,上面说给定非空引用值x,x.equals(x)会返回true,我们来试试:
public class Demo1
{
public static void main(String[] args)
{
Student s1 = new Student(1, "飞飞", 18);
Student s2 = new Student(2, "备备", 20);
System.out.println(s1.equals(s1));
System.out.println(s1.equals(s2));
}
}
class Student
{
private String name;
private int sid;
private int age;
public Student(){}
public Student(int sid, String name, int age)
{
this.sid = sid;
this.name = name;
this.age = age;
}
public String toString()
{
return "SID = "+sid+", Name = "+name+", Age = "+age;
}
}
/*
结果:
true
false
*/
可以看到,s1的地址是一个地址,所以s1.equals(s1),自己跟自己比较。当然返回true;s1跟s2地址不同,s1.equals(s2)返回的就是false了。还有,如果把主函数中第六行改成Student s2 = new Student(1, "飞飞", 18);再来比较,返回的还是false,因为地址不同。
好,现在需求来了:当一个对象的所有值都相等的情况下,我们要把它认为是同一个对象。这时候我们就要重写equals方法了,首先我们在jdk1.8.0_192\java\lang\中打开Object.java,在148行,有这样一段代码,就是equals的源代码:
我们按照要求重写这个代码,看到上面这个截图,考虑的是地址之间的比较,地址不同,返回的就是false,相同返回true。我们来写一下另一个代码:
public class b
{
public static void main(String[] args)
{
String str1 = new String("刘备");
String str2 = new String("刘备");
System.out.println(str1.equals(str2));
}
}
/*
结果:
true
*/
这时,可以看到在String中,改写了equals的方法,我们在同目录的String.java下找一下改写的equals代码:
public boolean equals(Object anObject) {
if (this == anObject) {//首先第一个判断,如果地址相同,直接可以返回true,要是不同,返回false
return true;
}
if (anObject instanceof String) {//然后地址不同的话,如果传进来的obj不是String类型,将其转换成String类型,名字叫anotherString
String anotherString = (String)anObject;
int n = value.length;//那就等于anotherString的长度
if (n == anotherString.value.length) {//如果长度相等
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {//n从大到下往下循环,看下面的if,如果其中有一个Ascii码不对,则返回false,不然就返回true
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
依照上面的来说,我们可以改一下我们的代码,看看看输出效果:
public class Demo1
{
public static void main(String[] args)
{
Student s1 = new Student(1, "飞飞", 18);
Student s2 = new Student(1, "飞飞", 18);
System.out.println(s1.equals(s2));
//System.out.println(s1.equals(s2));
}
}
class Student
{
private String name;
private int sid;
private int age;
public Student(){}
public Student(int sid, String name, int age)
{
this.sid = sid;
this.name = name;
this.age = age;
}
public String toString()
{
return "SID = "+sid+", Name = "+name+", Age = "+age;
}
public boolean equals(Object obj) //重写equals方法,来实现两个对象的比较
{
if(this == obj) //如果对象地址是它自己,可以直接返回true
{
return true;
}
if(obj instanceof Student)//如果对象是Student,可以接着判断
{
Student newobj = (Student)obj;
if(this.sid != newobj.sid)//比较一下身份,不对的话返回false
{
return false;
}
if(this.age != newobj.age)//比较一下年龄,不对的话返回false
{
return false;
}
if(!this.name.equals(newobj.name))//比较一下名字,不对的话返回false
{
return false;
}
return true;
}
return false;
}
}
/*
结果:
true
*/
protect void finalize()throwsThrowable
当垃圾回收器确定不存在该对象的更多引用时,对象的垃圾回收器调用此方法。子类重写finalize方法,以配置系统资源或进行其他清除。
public final Class<?> getclass()
返回此Object的运行时类。