Java之API详解之Object类的详细解析

4 Object类

4.1 概述

tips:重点讲解内容

查看API文档,我们可以看到API文档中关于Object类的定义如下:

Object类所在包是java.lang包。Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类;换句话说,该类所具备的方法,其他所有类都继承了。

查看API文档我们可以看到,在Object类中提供了一个无参构造方法,如下所示:

 

 

但是一般情况下我们很少去主动的创建Object类的对象,调用其对应的方法。更多的是创建Object类的某个子类对象,然后通过子类对象调用Object类中的方法。

4.2 常见方法

tips:重点讲解内容

常见方法介绍

我们要学习的Object类中的常见方法如下所示:

public String toString()				//返回该对象的字符串表示形式(可以看做是对象的内存地址值)
public boolean equals(Object obj)		//比较两个对象地址值是否相等;true表示相同,false表示不相同
protected Object clone()    			//对象克隆

案例演示

接下来我们就来通过一些案例演示一下这些方法的特点。

案例1:演示toString方法

实现步骤:

  1. 创建一个学生类,提供两个成员变量(name , age);并且提供对应的无参构造方法和有参构造方法以及get/set方法

  2. 创建一个测试类(ObjectDemo01),在测试类的main方法中去创建学生对象,然后调用该对象的toString方法获取该对象的字符串表现形式,并将结果进行输出

如下所示:

Student类

public class Student {

    private String name ;       // 姓名
    private String age ;        // 年龄

    // 无参构造方法和有参构造方法以及get和set方法略
    ...
        
}

ObjectDemo01测试类

public class ObjectDemo01 {

    public static void main(String[] args) {

        // 创建学生对象
        Student s1 = new Student("itheima" , "14") ;

        // 调用toString方法获取s1对象的字符串表现形式
        String result1 = s1.toString();

        // 输出结果
        System.out.println("s1对象的字符串表现形式为:" + result1);

    }

}

运行程序进行测试,控制台输出结果如下所示:

s1对象的字符串表现形式为:com.itheima.api.system.demo04.Student@3f3afe78

为什么控制台输出的结果为:com.itheima.api.system.demo04.Student@3f3afe78; 此时我们可以查看一下Object类中toString方法的源码,如下所示:

public String toString() {		// Object类中toString方法的源码定义
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

其中getClass().getName()对应的结果就是:com.itheima.api.system.demo04.Student;Integer.toHexString(hashCode())对应的结果就是3f3afe78。

我们常常将"com.itheima.api.system.demo04.Student@3f3afe78"这一部分称之为对象的内存地址值。但是一般情况下获取对象的内存地址值没有太大的意义。获取对象的成员变量的字符串拼接形式才

算有意义,怎么实现呢?此时我们就需要在Student类中重写Object的toString方法。我们可以通过idea开发工具进行实现,具体步骤如下所示:

  1. 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框

  2.  

  1. 选择toString,此时会弹出如下的对话框

     

同时选择name和age属性,点击OK。此时就会完成toString方法的重写,代码如下所示:

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

这段代码就是把Student类中的成员变量进行了字符串的拼接。重写完毕以后,再次运行程序,控制台输出结果如下所示:

s1对象的字符串表现形式为:Student{name='itheima', age='14'}

此时我们就可以清楚的查看Student的成员变量值,因此重写toString方法的意义就是以良好的格式,更方便的展示对象中的属性值

我们再来查看一下如下代码的输出:

// 创建学生对象
Student s1 = new Student("itheima" , "14") ;

// 直接输出对象s1
System.out.println(s1);

运行程序进行测试,控制台输出结果如下所示:

Student{name='itheima', age='14'}

我们可以看到和刚才的输出结果是一致的。那么此时也就证明直接输出一个对象,那么会默认调用对象的toString方法,因此如上代码的等同于如下代码:

// 创建学生对象
Student s1 = new Student("itheima" , "14") ;

// 调用s1的toString方法,把结果进行输出
System.out.println(s1.toString());

因此后期为了方便进行测试,我们常常是通过输出语句直接输出一个对象的名称。

小结:

  1. 在通过输出语句输出一个对象时,默认调用的就是toString()方法

  2. 输出地址值一般没有意义,我们可以通过重写toString方法去输出对应的成员变量信息(快捷键:atl + insert , 空白处 右键 -> Generate -> 选择toString)

  3. toString方法的作用:以良好的格式,更方便的展示对象中的属性值

  4. 一般情况下Jdk所提供的类都会重写Object类中的toString方法

案例2:演示equals方法

实现步骤:

  1. 在测试类(ObjectDemo02)的main方法中,创建两个学生对象,然后比较两个对象是否相同

代码如下所示:

public class ObjectDemo02 {

    public static void main(String[] args) {

        // 创建两个学生对象
        Student s1 = new Student("itheima" , "14") ;
        Student s2 = new Student("itheima" , "14") ;

        // 比较两个对象是否相等
        System.out.println(s1 == s2);

    }

}

运行程序进行测试,控制台的输出结果如下所示:

false

因为"=="号比较的是对象的地址值,而我们通过new关键字创建了两个对象,它们的地址值是不相同的。因此比较结果就是false。

我们尝试调用Object类中的equals方法进行比较,代码如下所示:

// 调用equals方法比较两个对象是否相等
boolean result = s1.equals(s2);

// 输出结果
System.out.println(result);

运行程序进行测试,控制台的输出结果为:

false

为什么结果还是false呢?我们可以查看一下Object类中equals方法的源码,如下所示:

public boolean equals(Object obj) {		// Object类中的equals方法的源码
    return (this == obj);
}

通过源码我们可以发现默认情况下equals方法比较的也是对象的地址值。比较内存地址值一般情况下是没有意义的,我们希望比较的是对象的属性,如果两个对象的属性相同,我们认为就是同一个对象;

那么要比较对象的属性,我们就需要在Student类中重写Object类中的equals方法。equals方法的重写,我们也可以使用idea开发工具完成,具体的操作如下所示:

  1. 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框

  1. 选择equals() and hashCode()方法,此时会弹出如下的对话框

 

 

点击next,会弹出如下对话框:

 

选择neme和age属性点击next,此时就会弹出如下对话框:

 

取消name和age属性(因为此时选择的是在生成hashCode方法时所涉及到的属性,关于hashCode方法后期再做重点介绍),点击Finish完成生成操作。生成的equals方法和hashCode方法如下:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Student student = (Student) o;
    return Objects.equals(name, student.name) && Objects.equals(age, student.age);	// 比较的是对象的name属性值和age属性值
}

@Override
public int hashCode() {
    return 0;
}

hashCode方法我们暂时使用不到,可以将hashCode方法删除。重写完毕以后运行程序进行测试,控制台输出结果如下所示:

true

此时equals方法比较的是对象的成员变量值,而s1和s2两个对象的成员变量值都是相同的。因此比较完毕以后的结果就是true。

小结:

  1. 默认情况下equals方法比较的是对象的地址值

  2. 比较对象的地址值是没有意义的,因此一般情况下我们都会重写Object类中的equals方法

  3.  

案例2:对象克隆

把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制

对象克隆的分类:

深克隆和浅克隆

浅克隆:

不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来

基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值。

Object类默认的是浅克隆

 

深克隆:

基本数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的

 

代码实现:

package com.itheima.a04objectdemo;

public class ObjectDemo4 {
    public static void main(String[] args) throws CloneNotSupportedException {
        // protected object clone(int a) 对象克隆 

        //1.先创建一个对象
        int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};
        User u1 = new User(1, "zhangsan", "1234qwer", "girl11", data);

        //2.克隆对象
        //细节:
        //方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去。
        //书写细节:
        //1.重写Object中的clone方法
        //2.让javabean类实现Cloneable接口
        //3.创建原对象并调用clone就可以了
        //User u2 =(User)u1.clone();

        //验证一件事情:Object中的克隆是浅克隆
        //想要进行深克隆,就需要重写clone方法并修改里面的方法体
        //int[] arr = u1.getData();
        //arr[0] = 100;

        //System.out.println(u1);
        //System.out.println(u2);


        //以后一般会用第三方工具进行克隆
        //1.第三方写的代码导入到项目中
        //2.编写代码
        //Gson gson =new Gson();
        //把对象变成一个字符串
        //String s=gson.toJson(u1);
        //再把字符串变回对象就可以了
        //User user =gson.fromJson(s, User.class);

        //int[] arr=u1.getData();
        //arr[0] = 100;

        //打印对象
        //System.out.println(user);

    }
}

package com.itheima.a04objectdemo;

import java.util.StringJoiner;



//Cloneable
//如果一个接口里面没有抽象方法
//表示当前的接口是一个标记性接口
//现在Cloneable表示一旦实现了,那么当前类的对象就可以被克降
//如果没有实现,当前类的对象就不能克隆
public class User implements Cloneable {
    private int id;
    private String username;
    private String password;
    private String path;
    private int[] data;




    public User() {
    }

    public User(int id, String username, String password, String path, int[] data) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.path = path;
        this.data = data;
    }

    /**
     * 获取
     *
     * @return id
     */
    public int getId() {
        return id;
    }

    /**
     * 设置
     *
     * @param id
     */
    public void setId(int id) {
        this.id = id;
    }

    /**
     * 获取
     *
     * @return username
     */
    public String getUsername() {
        return username;
    }

    /**
     * 设置
     *
     * @param username
     */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
     * 获取
     *
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     * 设置
     *
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * 获取
     *
     * @return path
     */
    public String getPath() {
        return path;
    }

    /**
     * 设置
     *
     * @param path
     */
    public void setPath(String path) {
        this.path = path;
    }

    /**
     * 获取
     *
     * @return data
     */
    public int[] getData() {
        return data;
    }

    /**
     * 设置
     *
     * @param data
     */
    public void setData(int[] data) {
        this.data = data;
    }

    public String toString() {
        return "角色编号为:" + id + ",用户名为:" + username + "密码为:" + password + ", 游戏图片为:" + path + ", 进度:" + arrToString();
    }


    public String arrToString() {
        StringJoiner sj = new StringJoiner(", ", "[", "]");

        for (int i = 0; i < data.length; i++) {
            sj.add(data[i] + "");
        }
        return sj.toString();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //调用父类中的clone方法
        //相当于让Java帮我们克隆一个对象,并把克隆之后的对象返回出去。

        //先把被克隆对象中的数组获取出来
        int[] data = this.data;
        //创建新的数组
        int[] newData =new int[data.length];
        //拷贝数组中的数据
        for (int i = 0; i < data.length; i++) {
            newData[i] = data[i];
        }
        //调用父类中的方法克隆对象
            User u=(User)super.clone();
        //因为父类中的克隆方法是浅克隆,替换克隆出来对象中的数组地址值
        u.data =newData;
        return u;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
API(应用程序编程接口)文档包含对应于导航栏中的项目的页面,如下所述。 概述 概述 页面是此 API 文档的首页,提供了所有软件包的列表及其摘要。此页面也可能包含这些软件包的总体描述。 软件包 每个软件包都有一个页面,其中包含它的类和接口的列表及其摘要。此页面可以包含四个类别: •接口(斜体) •类 •枚举 •异常 •错误 •注释类型 类/接口 每个类、接口、嵌套类和嵌套接口都有各自的页面。其中每个页面都由三部分(类/接口描述、摘要表,以及详细的成员描述)组成: •类继承图 •直接子类 •所有已知子接口 •所有已知实现类 •类/接口声明 •类/接口描述 •嵌套类摘要 •字段摘要 •构造方法摘要 •方法摘要 •字段详细信息 •构造方法详细信息 •方法详细信息 每个摘要条目都包含该项目的详细描述的第一句。摘要条目按字母顺序排列,而详细描述则按其在源代码中出现的顺序排列。这样保持了程序员所建立的逻辑分组。 注释类型 每个注释类型都有各自的页面,其中包含以下部分: •注释类型声明 •注释类型描述 •必需元素摘要 •可选元素摘要 •元素详细信息 枚举 每个枚举都有各自的页面,其中包含以下部分: •枚举声明 •枚举描述 •枚举常量摘要 •枚举常量详细信息 使用 每个已文档化的软件包、类和接口都有各自的“使用”页面。此页面介绍了使用给定类或软件包的任何部分的软件包、类、方法、构造方法和字段。对于给定的类或接口 A,其“使用”页面包含 A 的子类、声明为 A 的字段、返回 A 的方法,以及带有类型为 A 的参数的方法和构造方法。访问此页面的方法是:首先转至软件包、类或接口,然后单击导航栏中的“使用”链接。 树(类分层结构) 对于所有软件包,有一个 类分层结构 页面,以及每个软件包的分层结构。每个分层结构页面都包含类的列表和接口的列表。从 java.lang.Object 开始,按继承结构对类进行排列。接口不从 java.lang.Object 继承。•查看“概述”页面时,单击“树”将显示所有软件包的分层结构。 •查看特定软件包、类或接口页面时,单击“树”将仅显示该软件包的分层结构。 已过时的 API 已过时的 API 页面列出了所有已过时的 API。一般由于进行了改进并且通常提供了替代的 API,所以建议不要使用已过时的 API。在将来的实施过程中,可能会删除已过时的 API。 索引 索引 包含按字母顺序排列的所有类、接口、构造方法、方法和字段的列表。 上一个/下一个 这些链接使您可以转至下一个或上一个类、接口、软件包或相关页面。 框架/无框架 这些链接用于显示和隐藏 HTML 框架。所有页面均具有有框架和无框架两种显示方式。 序列化表格 每个可序列化或可外部化的类都有其序列化字段和方法的描述。此信息对重新实现者有用,而对使用 API 的开发者则没有什么用处。尽管导航栏中没有链接,但您可以通过下列方式获取此信息:转至任何序列化类,然后单击类描述的“另请参见”部分中的“序列化表格”。 常量字段值 常量字段值页面列出了静态最终字段及其值。
Java中的Object是所有类的根类,即所有类都直接或间接地继承自Object类。它提供了一些通用方法和功能,可以在所有对象中使用。 以下是一些Object类的常用方法和功能: 1. equals():用于比较两个对象是否相等。默认情况下,它比较的是对象的引用是否相等,但可以根据需要重写equals()方法来改变比较的逻辑。 2. hashCode():返回对象的哈希码。哈希码是根据对象的内部状态计算得到的一个整数,它用于在哈希表等数据结构中快速查找对象。 3. toString():返回对象的字符串表示。默认情况下,它返回对象的类名和哈希码,但可以根据需要重写toString()方法来返回自定义的字符串表示。 4. getClass():返回对象所属的类的Class对象。Class对象包含了有关类的信息,可以用于获取类的属性、方法等信息。 5. finalize():在对象被垃圾回收器回收之前调用。可以重写finalize()方法来执行一些清理操作。 6. clone():创建并返回一个对象的副本。要使用clone()方法,对象所属的类必须实现Cloneable接口。 7. wait()、notify()和notifyAll():用于线程间的协作。wait()方法使当前线程进入等待状态,notify()方法唤醒正在等待的线程,notifyAll()方法唤醒所有正在等待的线程。 此外,Object类还提供了一些其他方法,如getClassLoader()、finalize()、notify()、notifyAll()等。 需要注意的是,Object类中的这些方法都是被声明为final的,即不能被子类重写。这是为了确保这些方法的行为在所有对象中保持一致。 希望以上解答对您有所帮助!如果有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向着五星的方向

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值