面试官考我Object类中的所有方法及场景使用?我...

  咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java 知识点啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~


🏆本文收录于「Java进阶实战」专栏,数多年Java开发老兵项目累计经验,专业攻坚指数级提升,助你一臂之力,早日实现财富自由🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

  前几日,有位女读者遇到了一个很常见却又不好答的棘手面试题,于是特地向我诉苦了一波,于此,我怎么能见女不救,正所谓救人一命胜造七级浮屠。在此,我们就一起来再来温故一波对象的鼻祖Object类,及它的所有方法及使用场景吧。

解读Object类

  在Java中,我们都知道,Object类是所有类的根类,它位于类层次结构的顶端。Object类提供了一些基本的方法,这些方法被继承到所有的类中。以下是Object类中定义的主要方法及其用法:

toString()

  1. toString() - 返回对象的字符串表示,通常用于打印对象的简要信息。
   Object obj = new Object();
   System.out.println(obj.toString()); 

默认实现会返回类名@哈希码,源码实现如下:


  如上段代码是Java中用于生成对象的字符串表示形式的常见方法之一。它在默认情况下返回一个由类名和对象的哈希码组成的字符串,格式为类名@哈希码

拓展一下:

  1. getClass().getName() 返回对象所属类的名称。
  2. Integer.toHexString(hashCode()) 将对象的哈希码转换为十六进制字符串表示。

  因此,toString() 方法返回的字符串将类名和对象的哈希码连接在一起,以 @ 符号分隔。这样的字符串并不是特别有用,因为它不提供对象的实际内容信息,但是它可以用于快速检查对象的标识。

示例演示:

equals(Object obj)

  1. equals(Object obj) - 用于比较两个对象是否相等。默认实现是比较对象的引用,即是否为同一个实例。
   Object obj1 = new Object();
   Object obj2 = obj1;
   Object obj3 = new Object();
   System.out.println(obj1.equals(obj2)); // true,因为obj1和obj2是同一个对象
   System.out.println(obj1.equals(obj3)); // false,因为obj1和obj3是不同的对象

示例演示如下:

hashCode()

  1. hashCode() - 返回对象的哈希码值,该值在equals方法中用于比较对象的相等性。默认实现返回对象的系统标识符。

例如:

   Object obj = new Object();
   int hash = obj.hashCode();

示例演示:

在这里插入图片描述

getClass()

  1. getClass() - 获取运行时对象的类信息,返回一个Class对象。

例如:

   Object obj = new Object();
   Class<?> clazz = obj.getClass(); // 获取obj的运行时类类型

示例演示:

在这里插入图片描述

clone()

  1. clone() - 创建并返回对象的一个副本。默认实现是浅拷贝,即复制对象的引用值,而不是实际的内容。

例如:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:02
 */
public class testObject implements Cloneable{

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) {
        testObject obj = new testObject();
        try {
            testObject cloneObj = (testObject) obj.clone(); // 创建obj的一个浅拷贝
            System.out.println(cloneObj);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

示例演示:

在这里插入图片描述

拓展一下:

  在Java中,要使用clone()方法,首先需要确保被克隆的对象的类实现了Cloneable接口。如果一个类没有实现Cloneable接口,调用其clone()方法会抛出CloneNotSupportedException异常。

  另外,clone()这个方法使用了protected访问修饰符,因此只能在同一包内的类或者继承了这个类的子类中访问,因此只能在同一个包内或者子类中使用。

在这里插入图片描述

如果要克隆一个对象,最好的方式是通过实现Cloneable接口并重写clone()方法。示例代码如下:

class MyClass implements Cloneable {
    // 类的成员和方法

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

然后你可以这样使用:

MyClass obj = new MyClass();
MyClass cloneObj = (MyClass) obj.clone();

  若你直接对Object类的实例调用了clone()方法,但是Object类并没有实现Cloneable接口,会抛出CloneNotSupportedException异常。

wait()

  1. wait() - 使当前线程等待,直到另一个线程调用此对象的notify()notifyAll()方法。
   synchronized (obj) {
       try {
           obj.wait(); // 当前线程等待
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }

  示例这里我就先不着急给大家演示,同学们先看下我给大家解读的notify()方法学习后,我再一并给大家演示,毕竟这两是一起连用的,单独用没啥意义。

notify()

  1. notify() - 唤醒在此对象上等待的单个线程(如果有的话)。

使用例如:

   synchronized (obj) {
       obj.notify(); // 唤醒一个在此对象上等待的线程
   }

示例演示:

  这里联合notify(),关于Object类中使用wait()及notify()方法的示例演示:

定义启动类,将演示wait()、notify()方法效果。

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:38
 */
public class WaitNotifyExample {

    public static void main(String[] args) {
        Message message = new Message();

        // 创建一个等待线程
        Thread waiterThread = new Thread(new Waiter(message));

        // 创建一个通知线程
        Thread notifierThread = new Thread(new Notifier(message));

        // 启动线程
        waiterThread.start();
        notifierThread.start();
    }
}

定义一个Message类,用于在线程之间传递消息

package com.example.javase.bugTest.objectDemo;

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:38
 */
public class Message {
    private String content;

    public synchronized String getContent() {
        return content;
    }

    public synchronized void setContent(String content) {
        this.content = content;
    }
}

定义一个Waiter类,等待消息并打印。

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:38
 */
public class Waiter implements Runnable {
    private Message message;

    public Waiter(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        synchronized (message) {
            try {
                System.out.println("Waiter 等待中...");
                // 调用wait()方法,等待被通知
                message.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 收到通知后打印消息
            System.out.println("Waiter 收到通知: " + message.getContent());
        }
    }
}

定义一个Notifier类,负责发送通知。

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:38
 */
// Notifier类负责发送通知
public class Notifier implements Runnable {
    private Message message;

    public Notifier(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        synchronized (message) {
            // 设置消息内容
            message.setContent("你好,这是一条消息!");
            // 通知等待线程
            message.notify();
            System.out.println("Notifier 发送通知完毕");
        }
    }
}

  其中这个示例包含了一个Message类用于在线程之间传递消息,一个Waiter类等待消息并打印,一个Notifier类负责发送通知。在Waiter类中,使用了wait()方法来使线程进入等待状态,直到收到Notifier类发送的通知才继续执行。

实际运行结果展示:

拓展一下:

  如上示例演示了Object类中的wait()和notify()方法的使用,用于线程间的通信和同步。第一,我定义了一个Message类,它包含一个私有的字符串成员变量msg,以及一个getMessage()方法和setMessage()方法用于设置和获取消息。第二,定义了一个Waiter类和一个Notifier类,它们都实现了Runnable接口,用于作为线程执行体。Waiter类中的run()方法中调用了message.waitMessage()方法,而Notifier类中的run()方法中调用了message.setMessage()方法。第三,在WaitNotifyExample类的main()方法中,先创建了一个Message对象,并分别创建了一个等待线程waiterThread和一个通知线程notifierThread,它们都传入了同一个Message对象。最后,通过start()方法启动了这两个线程,实现了等待线程和通知线程的交互。

  总的来说,为大家演示了如何使用wait()和notify()方法实现线程间的等待和通知机制,从而实现线程间的协作。不知道大家可否能及时掌握,有疑问的及时评论区告知于我。

notifyAll()

  1. notifyAll() - 唤醒在此对象上等待的所有线程。

例如:

   synchronized (obj) {
       obj.notifyAll(); // 唤醒所有在此对象上等待的线程
   }

示例演示:

1、定义一个MessageProducer类,实现Runnable 接口,定位为一个消息生产者,当执行它的 run() 方法时,它会将一个新消息设置到 message 对象中,并通知所有等待中的线程。

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:51
 */
public class MessageProducer implements Runnable {
    private Message message;

    public MessageProducer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        synchronized (message) {
            // 生产消息
            message.setContent("New message: Hello, world!");
            // 通知所有等待的线程
            message.notifyAll();
        }
    }
}

2、定义一个MessageConsumer类,实现Runnable 接口,定位为一个消息消费者,目的是实现一个等待消息并处理的逻辑,通过线程的等待和唤醒机制,确保消息在到达后能够及时被消费。

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:51
 */
public class MessageConsumer implements Runnable {
    private Message message;

    public MessageConsumer(Message message) {
        this.message = message;
    }

    @Override
    public void run() {
        synchronized (message) {
            // 等待消息的到来
            while (message.getContent() == null) {
                try {
                    // 等待消息通知
                    message.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 收到消息后进行处理
            System.out.println("Received message: " + message.getContent());
        }
    }
}

3、定义一个mian主函数,用于创建生产者和消费者线程,最后通过启动线程,达到生产者线程将消息放入 Message 对象中,而消费者线程则从 Message 对象中获取消息并进行处理的效果。

package com.example.javase.bugTest.objectDemo;

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 19:51
 */
public class NotifyAllTest {

    public static void main(String[] args) {
        // 创建一个共享的消息对象
        Message message = new Message();

        // 创建生产者线程和消费者线程
        Thread producerThread = new Thread(new MessageProducer(message));
        Thread consumerThread1 = new Thread(new MessageConsumer(message));
        Thread consumerThread2 = new Thread(new MessageConsumer(message));

        // 启动线程
        producerThread.start();
        consumerThread1.start();
        consumerThread2.start();
    }
}

4、执行main函数本地测试结果如下:

  很明显,结果符合预期,生产者将消息传递后且唤醒在此对象上等待的所有线程(所有消费者线程),消费者拿到消息后并进行了打印。

拓展一下:

  如上示例演示了线程间如何通过共享对象进行通信。具体来说,创建了一个名为 NotifyAllTest 的公共类,其中包含一个名为 main 的静态方法。在 main 方法中:

  1. 创建了一个 Message 对象,这是一个自定义的消息对象,用于在生产者和消费者线程之间传递消息。
  2. 创建了一个生产者线程 (producerThread) 和两个消费者线程 (consumerThread1consumerThread2)。
  3. 启动了这三个线程。

  其中,MessageProducer 类和 MessageConsumer 类实现了 Runnable 接口,用于定义生产者和消费者线程的行为。生产者线程将消息放入 Message 对象中,而消费者线程则从 Message 对象中获取消息并进行处理。

  这个示例,我给大家演示了下线程间的基本通信和协作机制,但需要注意的是,它并没有提供线程安全的保障。在实际应用中,可能需要采取额外的措施来确保多线程环境下的数据安全性。

finalize()

  1. finalize() - 在垃圾收集器决定回收对象之前,由垃圾收集器调用此方法。这个 finalize 机制是不确定的,不保证会被调用,且在Java 9中已经被弃用。

简单使用实例例如:

   protected void finalize() throws Throwable {
       super.finalize();
       // 清理资源的代码
   }

示例演示:

好的,下面是一个关于Object类使用finalize()方法的示例:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-02 20:08
 */
public class FinalizeExample {

    // 定义一个类来演示finalize()方法
    static class MyObject {

        // 在对象销毁前调用finalize()方法
        @Override
        protected void finalize() throws Throwable {
            try {
                // 执行清理资源的操作
                System.out.println("对象被销毁前执行finalize()方法");
            } finally {
                super.finalize();
            }
        }
    }

    public static void main(String[] args) {
        // 创建一个对象
        MyObject obj = new MyObject();

        // 将对象设为null,以便触发垃圾回收
        obj = null;

        // 强制垃圾回收
        System.gc();

        // 等待一段时间以确保finalize()方法被调用
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

本地执行结果如下:

在这里插入图片描述

  在这个示例中,我定义了一个包含finalize()方法的内部类MyObject。在该方法中,我们可以执行清理资源的操作。在主函数中,我创建了一个MyObject对象,并将其设为null以便触发垃圾回收。然后,我手动调用了System.gc()方法来强制进行垃圾回收。最后,通过让主线程休眠一段时间,等待finalize()方法被调用。

小结

  大多数时候,你可能需要重写这些方法来提供特定的实现。例如,为了正确地比较两个对象是否相等,你可能需要重写equalshashCode方法。同样,为了实现深拷贝,你可能需要重写clone方法。

  请注意,Object类中的wait(), notify()notifyAll()方法是同步控制的一部分,它们只能在对象的监视器(由synchronized关键字实现)被当前线程持有时调用。不当使用这些方法可能导致死锁或其他同步问题。

… …

  ok,以上就是我这期的全部内容啦,如果还想学习更多,你可以看看专栏《Java进阶实战》中的其他硬货,每篇都是实打实的项目实战经验所撰。只要你每天学习一个奇淫小知识,日积月累下去,你一定能成为别人眼中的大佬的!功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程感兴趣的跨专业小白,都建议直接入手「滚雪球学Java」专栏;该专栏不仅免费,bug菌还郑重承诺,只要你学习此专栏,均能入门并理解Java SE,以全网最快速掌握Java语言,每章节源码均同步「Gitee」,你真值得拥有;学习就像滚雪球一样,越滚越大,带你指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同Java实战类型技术硬货,还可免费白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 20w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/710476.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CV预测:快速使用ResNet深度残差神经网络并创建自己的训练集

AI预测相关目录 AI预测流程&#xff0c;包括ETL、算法策略、算法模型、模型评估、可视化等相关内容 最好有基础的python算法预测经验 EEMD策略及踩坑VMD-CNN-LSTM时序预测对双向LSTM等模型添加自注意力机制K折叠交叉验证optuna超参数优化框架多任务学习-模型融合策略Transform…

基于BERT微调+模板填充快速实现文本转DSL查询语句

前言 Text2SQL是指将自然语言转化为类SQL查询语句&#xff0c;使得用户的查询文本可以直接实现和数据库交互&#xff0c;本文介绍一种以BERT为基础模型&#xff0c;通过模板填充来实现的Text2SQL算法和产品化。 内容摘要 Text2SQL任务说明模板填充的思路条件列选择子模型搭建…

深度搜索(递归实现)-计算岛屿最大面积

一、问题描述 二、解题思路 该题目采用递归方法&#xff1a;如果当前是“岛屿”&#xff0c;那么计算上下左右四个方向的面积值1作为当前岛屿总面积返回。 三、代码实现 import java.util.*;public class Solution {int maxArea0;/*** 代码中的类名、方法名、参数名已经指定&…

文章MSM_metagenomics(三):Alpha多样性分析

欢迎大家关注全网生信学习者系列&#xff1a; WX公zhong号&#xff1a;生信学习者Xiao hong书&#xff1a;生信学习者知hu&#xff1a;生信学习者CDSN&#xff1a;生信学习者2 介绍 本教程使用基于R的函数来估计微生物群落的香农指数和丰富度&#xff0c;使用MetaPhlAn prof…

【UIDynamic-动力学-UIGravityBehavior-重力行为 Objective-C语言】

一、UIGravityBehavior,重力行为, 1.接下来啊,我们一个一个来做, 新建一个项目,叫做:01-重力, 接下来,我们在这个ViewController里边, ViewDidLoad:里边,先写一段简单的代码, 我们写这么一段简单的代码,新建一个红色的UIView,把它显示在屏幕上, UIView *redVie…

03-RAG的核心 -结果召回和重排序

1 完整RAG应用的检索流程 2 Query预处理 2.1 意图识别 判断query问的是什么类型的问题&#xff0c;从而决定是否走RAG链路。 示例1&#xff1a; 深圳有什么好玩的 闲聊问题VDB支持哪些检索算法 产品常见问题 示例2&#xff1a; 为什么某个MongoDB实例内存占用过高 检查类…

博科SAN交换机初始化和Zone创建

1 初始化 博科的SAN交换机默认配置&#xff1a; 地址&#xff1a;10.77.77.77 账户&#xff1a;admin 密码&#xff1a;password 设备硬件查看 ***-SAN-1:admin> chassisshowFAN Unit: 1 Fan Direction: Reverse (Non-portside Intake) Time Awake: 0 daysP…

NOSQL -- ES

第三个我们比较常用的NOSQL类型的数据库 --- ES 介绍: ES的全称(Elasticsearch) ES是一个分布式全文搜索的引擎 也就是我们平常在购物, 搜索东西的时候常用的, 就是一个ES的类型, 分布式全文搜索引擎 查询原理: 1>分词: 在查询之前, 其会将一些数据拆分开, 按照词进行拆分…

计算机木马

病毒具有传播特性、恶意性 木马没有巨大的恶意&#xff0c;主要是帮黑客做些事情&#xff0c;没害你&#xff0c;没有那么广大的传播性

springboot宠物医院信息管理系统-计算机毕业设计源码04164

摘 要 现如今在中国&#xff0c;随着人民生活质量的逐渐提高&#xff0c;以及人民群众消费能力的日渐增长&#xff0c;各种各样的家养小动物&#xff0c;已经逐渐成为人类越来越亲密的生活伴侣。并且&#xff0c;现如今社会竞争及其激烈&#xff0c;人们的生活节奏越发急促、紧…

如何在 Windows 10/11 上编辑 PDF [4 种简单方法]

PDF 在大多数设备上都易于查看&#xff0c;但由于其设计用于查看&#xff0c;因此编辑起来可能比较棘手。编辑 PDF 可能比编辑 Microsoft Office 文档更具挑战性。 不用担心&#xff0c;我们已经为你做好了准备。无论你是想添加、删除还是插入文本或图片&#xff0c;你都可以使…

干部管理软件有哪些

随着信息技术的飞速发展&#xff0c;干部管理软件在各级党政机关、国企事业单位中扮演着越来越重要的角色。这些软件通过整合干部管理的各项业务流程&#xff0c;实现了干部信息的系统化、规范化和高效化管理。以下是几款主流的干部管理软件及其特点&#xff1a; 一、干部信息…

linux下C语言如何操作文件(一)

本篇我们简单介绍一下在linux中如何使用C语言操作文件,首先我们在项目中创建file_util.c源文件和file_util.h头文件如图: 我们先编辑file_util.h文件,定义好常用的函数,源代码如下: #ifndef FILE_UTIL_INCLUDED #define FILE_UTIL_INCLUDED#include <stdbool.h> #i…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 启动多任务排序(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 启动多任务排序(200分) 🌍 评测功能需要订阅专栏后私信联系…

AIGC绘画设计—揭秘Midjourney关键词魔法:让你的AI绘画瞬间起飞

在这个数字化飞速发展的时代&#xff0c;AI技术正以前所未有的速度改变着我们的生活和创作方式。在艺术创作领域&#xff0c;Midjourney作为一款强大的AI绘画工具&#xff0c;正逐渐受到越来越多创作者和爱好者的青睐。今天&#xff0c;我就来为大家揭秘Midjourney背后的关键词…

ORA-27090: Unable to reserve kernel resources for asynchronous disk I/O

一套11.2.0.4的rac库巡检&#xff0c;发现asm实例日志有如下报错 2.5.2 locate alert_${hst}.log tail -n 200 /oracle/app/grid/diag/asm/asm/ASM1/trace/alert_ASM1.log Errors in file /oracle/app/grid/diag/asm/asm/ASM1/trace/ASM1_ora_96212.trc: ORA-27090: Unable to…

工控机与普通电脑的区别对于工业自动化应用至关重要

商用计算机和工业计算机之间的相似之处可能多于差异之处。工业电脑利用了消费技术领域的许多进步&#xff0c;但增加了工业应用所必需的软件、编程、确定性和连接性。 专业人士表示&#xff1a;“从增加内存到摩尔定律所描述的处理能力的指数级增长&#xff0c;工业控制必将受…

吴恩达深度学习笔记:机器学习(ML)策略(1)(ML strategy(1))1.9-1.10

这里写自定义目录标题 第三门课 结构化机器学习项目&#xff08;Structuring Machine Learning Projects&#xff09;第一周 机器学习&#xff08;ML&#xff09;策略&#xff08;1&#xff09;&#xff08;ML strategy&#xff08;1&#xff09;&#xff09;1.9 可避免偏差&am…

新火种AI|苹果终于迈进了AI时代,是创新还是救赎?

作者&#xff1a;一号 编辑&#xff1a;美美 苹果的AI战略&#xff0c;能够成为它的救命稻草吗&#xff1f; 苹果&#xff0c;始终以其独特的创新能力引领着行业的发展方向。在刚结束不久的2024年的全球开发者大会&#xff08;WWDC&#xff09;上&#xff0c;苹果再次证明了…

重生奇迹mu魔剑士简介

出生地&#xff1a;勇者大陆 性 别&#xff1a;男 擅 长&#xff1a;近距离作战、武器特技&攻击魔法使用 转 职&#xff1a;剑圣&#xff08;3转&#xff09; 介 绍&#xff1a;当玩家账号中有一个220级以上的角色时&#xff0c;便可以创建职业为魔剑士的新角色&#x…