Obiect类是Java默认提供的一个类,Java中除了Obiect类,所有的类都存在继承关系,默认会继承Object类,即我们可以认为Object类是我们的顶级父类。
例如,我们来举一个例子证明Object接收所有类的对象
class Person{
}
class Student{
}
public class Test {
public static void main(String[] args) {
function(new Person());
function(new Student());
}
public static void function(Object obj){
System.out.println(obj);
}
}
所有类的对象都可以使用Object的引用进行接收,所以在开发中,Object类是参数的最高统一类型
在我们见识到Object类如此牛逼的操作后
Object类中到底存在哪些方法,又有哪些方法我们需要重点掌握(期末考试极有可能要考!!)
首先,我们来了解一下
Object类中存在哪些方法
在Object类中有
getClass()
hashCode()
equals(Object obj) { return (this == obj)
clone()
toString()
notify()
notifyAll()
wait()
finalize()
当然我们可以在idea中通过一些操作来具体查看Object类包含什么方法
1.打开idea,点击屏幕任意一处,按两下shift
2.点击classes,在输入栏输入Object
3.选择第一个Object.java.lang,进去之后你便可以看到Object类的所有方法和实现逻辑
下面我们详细说说toString(),equals(),hashcode() 方法
toString()方法的底层代码逻辑是
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
会默认返回:全类名(包名+类名)+@+哈希值的十六进制
当然这是在默认使用toString()方法的情况下,但在大多数时间下,是重写toString()方法来打印或者拼接对象中具体所需要输出的地方。
public class Test{
public static void main(String[] args) {
Person p = new Person("aniu", 21);
System.out.println(p);
//相当于
System.out.println(p.toString());
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 手动重写toString()
@Override
public String toString() {
return "name:" + this.name + " age:" + this.age;
}
}
equals()方法
equals()方法的底层代码逻辑
public boolean equals(Object obj){
return(this == obj)
}
我们首先要了解在Java中,==进行比较时
①如果==两侧是基本类型变量,比较的是变量中值是否相同
②如果==两侧是引用类型变量,比较的是变量地址是否相同
ps:基本数据类型: 引用数据类型
long、int、short、byte、float、double、boolean 类、接口、数组、枚举、注解、字符串等
③如果要比较对象中的内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址进行比较的
针对以上几点,我们可以举例一个例子,让大家清楚认识一下equals方法
class Person{
private String name;
private int age;
public Person(String name,int age){
this.age=age;
this.name=name;
}
}
public class Test {
public static void main(String[] args) {
Person p1=new Person("ggbond",20);
Person p2=new Person("ggbond",20);
int a=10;
int b=10;
System.out.println(a==b);
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
}
}
运行结果是: true
false
false
1.a==b,因为a和b都是基本数据类型,我们比较变量a、b两个的值,两个相等,则结果输出为true
2.p1与p2都是Person类的引用数据类型,尽管二者内容相同,但p1,p2都是new在堆上,二者引用变量地址不同,结果输出就为false
3.我们调用了equals方法,但equals方法与2类似,故也输出结果是fasle
如果我们想把equals方法比较的是里面的内容而不是,p1、p2的地址,我们就需要重写equals方法
然后进行比较
public boolean equals(Object obj){
if(obj==null){
return false;
}
if(this==obj){
return true;
}
//不是Person类对象
if(!(obj instanceof Person)){
return false;
}
Person person=(Person)obj;
return this.name.equals(person.name)&&this.age==person.age;
}
则结果就为
所以我们在比较对象内容是否相同,就要学会重写equals方法
hashCode()方法
底层代码逻辑是
public native int hashCode();
为一个native方法,底层是由C/C++代码写成,我们无法看到
同样的,我们举一个例子,用原hashCode()方法
class Person{
public String name;
public int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
}
public class Test {
public static void main(String[] args) {
Person p1=new Person("ggbond",20);
Person p2=new Person("ggbond",20);
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
}
}
我们可以看到,两个对象的hash值不一样
在我们重写hashCode()方法后
public int hashCode(){
return Objects.hash(name,age);
}
此时哈希值一样,因此
1.hashCode方法可用来确定对象在内存中存储的位置是否相同
2.事实上hashCode()方法在散列表中才有用,其他大部分下我们都用不上hashCode()
因此,我们在如果说到哈希表的时候,如果需要把两个一样的对象,想放到同一个位置,就要重写hashCode()方法。