一.Object类

1.概念

Object类是Java默认提供的一个类。Java中除了Object类,所有类都是存在继承关系的。因为默认Object类是其它所有类的父类,默认会继承Object类,所有类的对象都可以使用Object的引用进行接收。

2.使用事例

如:

Student类文件中:

public class Student{

int age;

public Student(int age){

this.age=age;

}

}

Test类文件中:

public class Test{

public static void  addressPrint(Object  obj){

System.out.println(obj)

}

public static void main(String[] args){

Student shushu=new Student(19);

addressPrint(shushu);

}

}

测试结果:

将shushu的地址打印出来了,可以看到我传的的明明是Student类,addressPrint方法的形参类型是Object类,却并不会报错反而能顺利运行,印证了Object类是其它类的父类这一点。

二.Object类中定义好的方法

这里面定义好的方法使用范围非常广,可以用快捷键调出来重写(方法在上一篇中)。

1.介绍有哪些方法

【1】toString

【2】equals

【3】hashCode

【4】getClass

【5】clone

【6】notify/notifyAll

【7】wait

今天先介绍三种

2.toString方法

我们在面向对象过程中,可以发觉到对象具有很多个属性,而我们要想快速清晰的打印对象所具有的基本信息就必须用到toString方法,方便调试,我们不可能挨个写成(System.out.print(对象.属性1+对象.属性2......))的表达方式,比较混乱,而且不好控制格式。这个时候我们只需要在所需要打印的对象所属类中用快捷键重写toString方法,在后面主类中正常写上(System.out.print(对象))即可整齐输出所有属性信息。

【1】在Object中的原型

public class Object{

retrun getClass().getName()+"@"+Integer.toHexString(hasCode());

}

【2】在类中的语法形式

如:

Student类文件中:

public class Student{

int age;

String name;

@Override
public String toString() {
    return "Student{" +
            "age=" + age +
            ", name='" + name + '\'' +
            '}';
}//重写toString方法

public Student(int age,String name){

this.age=age;

this.name=name;

}

}

在Test测试类中调用:

public class Test{

public static void main(String[] args){

Student student=new Student(20,"shushu");

System.out.println(student);

}

}

测试结果:

前面是该对象的类名,需要打印出对象的哪些属性就在快捷页面勾选上,没选上的属性,即使在实例化的时候赋予了初值,在打印结果中也不会出现。

//快捷页面中勾选所需打印属性

3.对象比较equals方法

在Java中,利用==进行比较时,会出现三种情况

第一种如果==两边是基本类型变量,则比较的是变量中的值是否相同

第二种如果==两边是引用类型变量,则比较的是引用变量的地址是否相同

第三种就是你用眼睛都能看到引用类型变量内容或者是对象中的内容明明是相等的,但用==进行比较,输出的还是false,原因就在于==在对两侧引用类型内容进行比较时,比较的是地址,如果你想要比较的是内容,那么就可以调用Object类中的equals方法然后进行快捷键重写,最后进行使用

【1】Object类中equals方法原型

public boolean equals(Object obj){

return (this == obj):

}

【2】不重写的equals方法进行比较的展示

Student类文件中:

puclic class Student{

String name;

int age;

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

}

Test测试类文件中:

public class Test{

        public static void main(String[] args){
                int a=10;
                int b=20;
                Student student1=new Student("shushu",20);
                Student student2=new Student("shushu",20);
                System.out.println(a==b);//基本类型变量比较
                System.out.println(student1==student2);//利用==对引用类型变量比较
                System.out.println(student1.equals(student2));//利用未重写的equals方法进行比较(为什么这里明明没有看到equals,却能直接调用,原因在于equals是Object类中定义好的方法,Object是所有类的父类,继承了equals方法)
        }

        }

测试结果:

可以看到全部输出的是false,基本类型变量由于值本身就不同输出false,另外的引用类型比较,我们眼睛可以看到是一样的内容,但利用==和未重写的equals方法比较时,比较的是地址。

【3】重写后的equals方法进行比较展示

Student类文件中:

puclic class Student{

String name;

int age;

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return age == student.age && name.equals(student.name);
}//利用快捷键重写equals方法

}

Test测试类文件中:

public class Test{

        public static void main(String[] args){
                int a=10;
                int b=20;
                Student student1=new Student("shushu",20);
                Student student2=new Student("shushu",20);
                System.out.println(a==b);//基本类型变量比较
                System.out.println(student1==student2);//利用==对引用类型变量比较
                System.out.println(student1.equals(student2));//利用重写过后的equals方法进行比较

}

}

测试结果:

可以明显看到重写过后的equals方法输出的是true。

【4】特殊注意点:

String temp1="haha";
String temp2="haha";
System.out.println(temp1==temp2);
System.out.println(temp1.equals(temp2));

测试结果:如果在上面测试类中添加这四行,运行后会发现这两行都会输出true。即使Student类没有重写equals方法也是输出true

疑问点:为什么会这样?刚才不是说引用类型变量利用==比较的是地址,没有重写equals方法也是比较地址吗?为何还是输出true的结果。

答案:因为String是Java的特殊引用类型,它里面早就重写好了equals方法跟Student类有没有重写equals方法无关(解答第二句)

再者是因为字符串常量池的特性,当你去写String temp1="haha";时,JVM会先去字符串常量池里找有没有"haha",如果没有就创建,当写String temp2="haha";时,JVM发现常量池里面已经有一个"haha"了,直接会让temp2也指向与temp1相同的地址。自然二者返回的都是true(解答第一句)。

思考:那么怎么样才能打破字符串常量池,让temp1==temp2;重新输出为false?

答案:String temp1=new String("haha");
        String temp2=new String("haha");//将初始化写出这样子即可

4.快速定位对象存储位置的hashCode方法

【1】作用

返回一个整数(哈希码,数据结构内容后面会继续学习),代表对象的”哈希标识“。哈希集合会用这个值快速定位对象的存储位置,从而提高查找/去重的效率

【2】Object类中的hashCode方法原型

public native int hashCode();

该方法是一个native方法,底层是由c和c++代码写的,我们看不到。

【3】不重写的hashCode方法进行展示

Student类文件中:

puclic class Student{

String name;

int age;

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

}

Test测试类文件中:

public class Test{

        public static void main(String[] args){
                int a=10;
                int b=20;
                Student student1=new Student("shushu",20);
                Student student2=new Student("shushu",20);
                System.out.println(student1.hashCode());
                System.out.println(student2.hashCode());

}

}

测试结果:

可以看到两个对象的哈希码不同

【4】重写过后hashCode方法展示

Student类文件中:

puclic class Student{

String name;

int age;

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return age == student.age && name.equals(student.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}
//重写的hashCode,可以看到重写了hashCode连带着equals也被重写了,其实它们是相当于绑定在一起的,用快捷键重写其中一个必定就会重写另一个,不要轻易删除,其中必须遵守的条约为:【1】如果两个对象equals方法返回true,那么它们的hashCode返回值必须相等;【2】如果两个对象hashCode返回值不相等,那么equals方法一定返回false;【3】但hashCode返回值相等时,equals方法返回的可能是true也可以是false,这叫哈希冲突。

}

Test测试类文件中:

public class Test{

        public static void main(String[] args){
                int a=10;
                int b=20;
                Student student1=new Student("shushu",20);
                Student student2=new Student("shushu",20);
                System.out.println(student1.hashCode());
                System.out.println(student2.hashCode());

}

}

测试结果:

可以看到两个对象之间的hashCode返回值相等了。

【5】误区

看到上面hashCode方法的作用,不禁疑问:为什么利用了hashCode之后两个对象的地址就变相同了呢?

首先,我们要明确hashCode的返回值叫哈希码,哈希码并不等于不等于对象地址,也就是说上面返回的是哈希码而不是对象地址,哈希码在默认情况(未重写时)下是根据对象地址计算出来的整数,所以默认hashCode和地址强相关,但重写之后哈希码会根据对象属性重新计算(与地址无关)故会变得相同。

 

 

 

 

 

 

 

 

 

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐