目录
3.Object
Object类在Java.lang包下
然后往下看 public class Object不继承自任何类。
因为类Object是类层次结构的根类。每个类都是Object作为超类,所以说Object是所有类的祖宗类。所有类都直接或者间接的继承自Object。
Object只有一个无参构造方法。回想一下面向对象中学过子类访问父类的构造方法默认的第一行有一个super();空参的方法,访问的是父类的无参构造方法,为什么呢?因为它们的老祖宗类里面只有一个构造方法。
Object中的方法我们主要学习:
equals(Object obj)和toString()方法
3.1Object类的概述
Object是类层次结构的更,每个类都可以将Object作为超类。所有类都有直接或者间接的继承自该类。
构造方法:public Object();
回想面向对象中,为什么说子类的构造方法默认访问的是父类的无参构造方法?
因为它们的顶级父类只有无参构造方法。
代码讲解toSting:
/*
学生类
*/
class Student {
//1.成员变量
private String name;
private int age;
//2.无参带参构造方法
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//3.get/set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//12.重写toString方法
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/*
它最终是是一个字符串,它里面包含了name和age的信息
*/
}
/*
测试类:
Object 是类层次结构的根,每个类都可以将Object作为超类.
所有类都直接或者间接的继承自该类
选中println右键选择Go tO中的Declaration找到方法的
声明处,或者快捷键Ctrl+b
建议所有子类都重写此方法
如何重写呢?
在Student类中
我们可以手动写,也可以自动生成
按下Alt+ins键找到toString选中两个成员变量点OK
*/
public class ObjectDemo {
public static void main(String[] args) {
//4.创建学生对象
Student s = new Student();
s.setName("林青霞");
s.setAge(30);
//5.输出s看看是否s跟这两个成员变量有关系
System.out.println(s);
//6.得到com.itheima01.Student@6e8dacdf
//7.发现这s跟这两个变量好像没有任何关系
/*
8.选中println右键选择Go tO中的Declaration找到方法的
声明处,或者快捷键Ctrl+b
*/
/*
9.然后就可以看到我们传递的参数就是:
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
然后就可以看到传递的参数x使用的是valueOf();方法,
然后继续跟进查看这个方法
可以看到valueOf();方法:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
然后再看传递的参数是obj,obj使用的是toString();方法
选中toString方法再继续跟进,
然后就可以看到最终就走到了这里:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
然后就可以看到这个println();方法到底做了什么事情
我们调用printl方法把s传递到public void println(Object x)中的形参这里
x = s,然后调用valueOf()方法,把x传递进去.
然后就相当于public static String valueOf(Object obj)这里的obj就相当于x
接着判断obj == null,obj是x,x是s,而我们的s是我们new出来的,所有它不可能是null,
所以obj不可能是null,这个obj.toString()是(obj == null)表达式结果,obj调了一个
toString方法,我们在帮助文档中看到Object确实是有toString方法的,而最终其实用的对象
是Student这个对象的,而我们学生类里面是没有toString方法的,在Student类中其实是隐含了
一个继承关系就是,Student extends Object,也就是说虽然Student里面没写,但是它可以用
它父亲里面的,所以obj.toString();这里toString方法使用的是Object中的方法,而我们看到
了Object类中的toString方法做的事情就是做的
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}这样一个事情.可以看到它返回的是一个字符串,来看一下这个格式:
getClass().getName(),它拿的就是类的全路径名,就是带包名的内容:
om.itheima01.Student
然后拿@这个符号来拼接了一下
接着来了一串数据值Integer.toHexString(hashCode());这个就是结果中的6e8dacdf这一串数据值
看到这里我们就可以知道原来它底层调用的是一个toString方法,
得到的这样的om.itheima01.Studentc@6e8dacdf一个信息,
而我们学生类没有toString方法,但是它继承了Object所以它使用的是Object里面的toString方法
我们来测试一下
*/
//10.通过学生类对象调用父类Object的toString方法
System.out.println(s.toString());//com.itheima01.Student@6e8dacdf
/*11.这里得到的内容和上面的内容是一样的,所以说它默认底层调了toString方法
为什么toString方法输出的是这个内容呢.我们得到帮助文档中查看一下
toString方法的讲解:
返回对象的字符串表示形式。 通常, toString方法返回一个“文本表示”此对象的字符串。
结果应该是简洁但信息丰富的表示,便于人们阅读。 建议所有子类都覆盖此方法。
但是我们得到的结果是:com.itheima01.Student@6e8dacdf这个结果并不让人容易阅读
所以这个方式不好.
还说了,建议所有子类都覆盖此方法,覆盖就是重写的意思.
如何重写呢?看最上面测试类写的重写方法.
重写之后再执行,就可以得到:
Student{name='林青霞', age=30}
Student{name='林青霞', age=30}
那么这个信息就是我们想要得到的简洁扼要的信息。
以后我们写Student这种类的时候最好就要重写toString方法,这样我们在创建对象之后
给对象的成员变量赋值之后,直接输出这个对象的时候输出的就是能够看得懂的一个字符串.
*/
}
}
3.2Object类的常用方法
先到代码演示再小结:
class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//3.根据2的描述重写equals方法
@Override
public boolean equals(Object o) {
/*
5.我们通过s1调用equals方法把s2传递到equals方法的形参里面
然后再equals里面就有一个this == s1,然后Object o = s2,
*/
//this = s1;
//Object o = s2;
/*
6.接着往下执行第一个判断if (this == o) return true;
这里比较的是地址是否相同,如果地址值相同,那么就是同一个对象,
同一个对象的内容肯定是相同的,就返回true.如果不是就接着往下执行
*/
if (this == o) return true;
/*
7.这里是使用逻辑或来判断,他先判断参数o是否为null,如果参数为null就
没有必要比了,直接返回false就可以了,因为我们使用对象调用方法,传递的
参数是null,那么它的成员变量值跟我们对象的值肯定是不一样的,
接着就是getClass() != o.getClass(),就是判断这两个对象是否来自
同一个类,如果这两个对象来自不是同一个类,那么它们的成员内容应该是不相同的
所以就返回false这里的两种情况只要有一种情况满足就返回false.
来看一下我们的两个对象,参数o = s2,不是null,并且来自的是同一个类,
所以不追执行这一条判断语句,接着往下执行
*/
if (o == null || getClass() != o.getClass()) return false;
/*
8.做了一个动作把这个o强转为Student,我们在ObjectDemo类中把s2传递过来
相当于把s2传递给了equals方法的形参Object o,这个就是向上转型,而
(Student) o这个动作是向下转型,而s2是Student类型的,把这个o强转成studen
类型的是没问题的.那么这个做完之后,student就代表的s2,接着往下执行.
*/
Student student = (Student) o;
/*
9.首先判断(age != student.age),第一个age什么都没写,其实隐含了this,也就是
(this.age != student.age),也就是这里比的是s1.age和s2.age,用不等于比的,
然后s1的age是30,s2的age也是30所以它们是等于的,就不会返回false.
*/
if (age != student.age) return false;
/*
10.然后判断name是否不等于null,它不等于null才能去掉方法,这里的name隐含了this,
所以name是s1的name,s1的name是林青霞不等于null,然后就回来调equals方法,接着
来和s2.name也就是student.name进行比较,比的是它两姓名的内容是否相同,
而s1和s2中的name是String类型的,所以使用的String里面的equals方法,
String里的equals方法比的就是内容是否相同,然后它们的内容是相同的,所以在这里
最终的结果是true,所以它最终返回了true
*/
return name != null ? name.equals(student.name) : student.name == null;
}
}
/*
测试类:
public boolean equals (Object obj):指示一些其他对象是否等于此
*/
public class ObjectDemo {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(30);
Student s2 = new Student();
s2.setName("林青霞");
s2.setAge(30);
//需求:比较两个对象的内容是否相同
// System.out.println(s1 == s2);//false
/*因为s1,s2是new出来的,代表的是地址值
所以这个比较的是地址值所以结果是false
这种方式是不可取的,所以我们要把它注释掉
*/
System.out.println(s1.equals(s2));//false
/*
1.为什么还是得到false呢?我们去看一下源码
public boolean equals(Object obj) {
return (this == obj);
}
equals方法内部它有一个this
this就是谁调equals,它就代表谁,
而s2我们就把它传递进去了,obj就等于s2
而(this == obj);这个动作还是比较的是s1和s2的地址值.
而s1和s2的地址值是不同的所以返回的是false,
*/
/*
2.我们要单独的去比较s1和s2中name和age的值是否都相同,
那么这个时候我们通过equals方法是可以实现的,但是这个
equals方法,默认Object里面的equals方法比较的是地址,
所以说我们要重写equals方法,如何重写呢?
手写或者自动生成Alt+ins找到equals() and hashCode()选项
这样会重写两个,我们删掉hasCode方法就可以了
然后他会弹出模板,我们选择IntelliJ Default模板.然后全选next
*/
/*
4.重写完之后,然后我们右键执行一下就可以得到true
它怎么就满足了我们的需求呢?
回到学生类我们来解释一下重写的equals方法
*/
}
}
小结:
toString默认打的是类的全路径加上@加上一个数据值,没有什么意义所以建议所有子类重写该方法。