买做指甲的材料在哪个网站,教学督导网站建设报告,建设网站的个人心得体会,产品设计公司网站咦咦咦#xff0c;各位小可爱#xff0c;我是你们的好伙伴——bug菌#xff0c;今天又来给大家普及Java 知识点啦#xff0c;别躲起来啊#xff0c;听我讲干货还不快点赞#xff0c;赞多了我就有动力讲得更嗨啦#xff01;所以呀#xff0c;养成先点赞后阅读的好习惯各位小可爱我是你们的好伙伴——bug菌今天又来给大家普及Java 知识点啦别躲起来啊听我讲干货还不快点赞赞多了我就有动力讲得更嗨啦所以呀养成先点赞后阅读的好习惯别被干货淹没了哦~ 本文收录于「Java进阶实战」专栏数多年Java开发老兵项目累计经验专业攻坚指数级提升助你一臂之力早日实现财富自由欢迎大家关注收藏持续更新中upupup 环境说明Windows 10 IntelliJ IDEA 2021.3.2 Jdk 1.8前几日有位女读者遇到了一个很常见却又不好答的棘手面试题于是特地向我诉苦了一波于此我怎么能见女不救正所谓救人一命胜造七级浮屠。在此我们就一起来再来温故一波对象的鼻祖Object类及它的所有方法及使用场景吧。
解读Object类 在Java中我们都知道Object类是所有类的根类它位于类层次结构的顶端。Object类提供了一些基本的方法这些方法被继承到所有的类中。以下是Object类中定义的主要方法及其用法
toString()
toString() - 返回对象的字符串表示通常用于打印对象的简要信息。 Object obj new Object();System.out.println(obj.toString()); 默认实现会返回类名哈希码源码实现如下 如上段代码是Java中用于生成对象的字符串表示形式的常见方法之一。它在默认情况下返回一个由类名和对象的哈希码组成的字符串格式为类名哈希码。
拓展一下
getClass().getName() 返回对象所属类的名称。Integer.toHexString(hashCode()) 将对象的哈希码转换为十六进制字符串表示。 因此toString() 方法返回的字符串将类名和对象的哈希码连接在一起以 符号分隔。这样的字符串并不是特别有用因为它不提供对象的实际内容信息但是它可以用于快速检查对象的标识。
示例演示 equals(Object obj)
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()
hashCode() - 返回对象的哈希码值该值在equals方法中用于比较对象的相等性。默认实现返回对象的系统标识符。
例如 Object obj new Object();int hash obj.hashCode();示例演示 getClass()
getClass() - 获取运行时对象的类信息返回一个Class对象。
例如 Object obj new Object();Class? clazz obj.getClass(); // 获取obj的运行时类类型示例演示 clone()
clone() - 创建并返回对象的一个副本。默认实现是浅拷贝即复制对象的引用值而不是实际的内容。
例如
/*** Author bug菌* Source 公众号猿圈奇妙屋* Date 2024-04-02 19:02*/
public class testObject implements Cloneable{Overrideprotected 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 {// 类的成员和方法Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}然后你可以这样使用
MyClass obj new MyClass();
MyClass cloneObj (MyClass) obj.clone();若你直接对Object类的实例调用了clone()方法但是Object类并没有实现Cloneable接口会抛出CloneNotSupportedException异常。
wait()
wait() - 使当前线程等待直到另一个线程调用此对象的notify()或notifyAll()方法。 synchronized (obj) {try {obj.wait(); // 当前线程等待} catch (InterruptedException e) {e.printStackTrace();}}示例这里我就先不着急给大家演示同学们先看下我给大家解读的notify()方法学习后我再一并给大家演示毕竟这两是一起连用的单独用没啥意义。
notify()
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;}Overridepublic 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;}Overridepublic 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()
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;}Overridepublic 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;}Overridepublic 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 方法中
创建了一个 Message 对象这是一个自定义的消息对象用于在生产者和消费者线程之间传递消息。创建了一个生产者线程 (producerThread) 和两个消费者线程 (consumerThread1 和 consumerThread2)。启动了这三个线程。 其中MessageProducer 类和 MessageConsumer 类实现了 Runnable 接口用于定义生产者和消费者线程的行为。生产者线程将消息放入 Message 对象中而消费者线程则从 Message 对象中获取消息并进行处理。 这个示例我给大家演示了下线程间的基本通信和协作机制但需要注意的是它并没有提供线程安全的保障。在实际应用中可能需要采取额外的措施来确保多线程环境下的数据安全性。
finalize()
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()方法Overrideprotected 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()方法被调用。
小结 大多数时候你可能需要重写这些方法来提供特定的实现。例如为了正确地比较两个对象是否相等你可能需要重写equals和hashCode方法。同样为了实现深拷贝你可能需要重写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年度十佳博主掘金多年度人气作者Top4051CTO年度博主Top12掘金/InfoQ/51CTO等社区优质创作者全网粉丝合计 20w硬核微信公众号「猿圈奇妙屋」欢迎你的加入免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料你想要的我都有关键是你不来拿。