《Effective Java》学习笔记——第1部分 创建对象和销毁对象的最佳实践

文章目录

    • 第1部分 创建和销毁对象
      • 一、前言
      • 二、创建和销毁对象最佳实践内容
        • 1. 优先使用工厂方法而非直接使用构造器
        • 2. 避免创建不必要的对象
        • 3. 避免使用过多的构造器
        • 4. 避免使用原始类型(Raw Types)
        • 5. 避免创建对象的过度依赖
        • 6. 清理资源和关闭对象(显式地管理对象生命周期)
        • 7. 避免使用 finalize()` 方法
      • 三、小结


image-20250121160352402

第1部分 创建和销毁对象

一、前言

《Effective Java》共有多个章节,每个章节提供了若干条建议或最佳实践,整理了对应章节关键的实践内容,用于自己后续代码开发过程中,参考对照,自查代码习惯,从而提升输出的代码质量。

二、创建和销毁对象最佳实践内容

1. 优先使用工厂方法而非直接使用构造器
  • 原因:直接调用构造器来创建对象的方式灵活性较差,尤其是在构造过程中可能需要大量的复杂参数时,代码就会变得不易维护和阅读。
  • 工厂方法的好处:工厂方法能够提供更高的灵活性,可以在方法内部控制对象的创建过程,并且可以对对象的创建方式进行封装。
  • 示例
    // 使用构造器创建对象
    Date date = new Date(2025, 1, 21);// 使用工厂方法创建对象
    public static Date newInstance(int year, int month, int day) {return new Date(year, month, day);
    }
    
2. 避免创建不必要的对象
  • 原因:频繁的对象创建会消耗更多的内存和处理时间,因此尽量避免无谓的对象实例化。
  • 实践:例如,对于不可变的对象或常量,可以考虑使用单例模式、缓存技术或享元模式,来避免重复创建相同的对象。
  • 示例:使用静态常量替代重复创建相同的对象。
    // 不必要的对象创建
    String a = new String("Hello");// 更好的做法
    String b = "Hello";  // 直接使用字符串字面量
    
3. 避免使用过多的构造器
  • 原因:过多的构造器会增加类的复杂性,并导致 API 不易使用,尤其是当类的构造器参数很多时,调用者很难确定需要传入哪些参数。
  • 解决方法:使用 构建者模式(Builder Pattern) 来提供更清晰、更易于使用的构造方式。通过构建者模式,类的实例化变得更加灵活和可维护。
  • 示例:使用构建者模式
    public class NutritionFacts {private final int servings;private final int calories;public static class Builder {private final int servings;private int calories = 0;public Builder(int servings) {this.servings = servings;}public Builder calories(int val) {calories = val;return this;}public NutritionFacts build() {return new NutritionFacts(this);}}private NutritionFacts(Builder builder) {servings = builder.servings;calories = builder.calories;}
    }
    
4. 避免使用原始类型(Raw Types)
  • 原因:原始类型会导致类型安全问题,并且不符合泛型的设计原则,因此应该避免使用原始类型。
  • 实践:使用 Java 泛型来确保类型的安全性。
  • 示例:避免原始类型
    // 不安全的原始类型
    List list = new ArrayList();
    list.add("Hello");// 使用泛型
    List<String> list = new ArrayList<>();
    list.add("Hello");
    
5. 避免创建对象的过度依赖
  • 原因:频繁地创建对象会导致内存占用增加、垃圾回收压力增大,甚至会影响性能。
  • 实践:使用对象池、缓存等技术来重用对象,避免频繁的创建和销毁。
  • 示例
    // 使用对象池技术可以避免频繁的创建和销毁对象
    ObjectPool<Connection> pool = new ObjectPool<>(new ConnectionFactory());
    Connection conn = pool.borrowObject();
    
6. 清理资源和关闭对象(显式地管理对象生命周期)
  • 原因:如果对象占用系统资源(如数据库连接、文件句柄等),如果不手动关闭,会导致资源泄漏。
  • 实践:使用 try-with-resources 或显式调用 close() 方法来确保资源的正确释放。
  • 示例
    // 使用 try-with-resources 自动关闭资源
    try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {// 处理文件
    } catch (IOException e) {e.printStackTrace();
    }
    
7. 避免使用 finalize()` 方法
  • 原因finalize() 方法是在对象被垃圾回收器回收前调用的,但它的不确定性和执行时机会导致不可靠的资源释放。
  • 实践:尽量避免使用 finalize(),而是使用 try-with-resources 或手动清理资源。
  • 示例
    // 不推荐使用 finalize() 方法来管理资源
    @Override
    protected void finalize() throws Throwable {try {// 资源清理代码} finally {super.finalize();}
    }
    

三、小结

在“创建和销毁对象”部分中,书中提出了许多关于如何高效、安全地创建和销毁对象的建议。使用工厂方法避免过度构造使用对象池清理资源等方式,能够帮助程序员编写出更加健壮、性能优越的 Java 程序。这些实践不仅有助于避免性能瓶颈,也使得代码更加清晰和易于维护。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决conda create速度过慢的问题

问题 构建了docker容器 想在容器中创建conda环境&#xff0c;但是conda create的时候速度一直很慢 解决办法 宿主机安装的是anaconda 能正常conda create,容器里安装的是miniforge conda create的时候速度一直很慢&#xff0c;因为容器和宿主机共享网络了&#xff0c;宿主机…

【知识分享】PCIe5.0 TxRx 电气设计参数汇总

目录 0 引言 1 参考时钟--Refclk 2 发射端通道设计 3 发送均衡技术 4 接收端通道设计 5 接收均衡技术 6 结语 7 参考文献 8 扩展阅读 0 引言 PCI Express Base Specification 5.0的电气规范中&#xff0c;关键技术要点如下&#xff1a; 1. 支持2.5、5.0、8.0、16.0和3…

Java 的初认识(一)

好久不见兄弟们&#xff01;之前更新完 C 语言的内容之后呢&#xff0c;我是做了一个“ 短暂 ”的休息昂&#xff0c;当然我自己的学习是没有停歇的&#xff0c;只是在更新博客这上面休息了一下&#xff0c;主要还是想让自己先把这部分的知识掌握透彻了之后&#xff0c;再来为大…

2024年美赛C题评委文章及O奖论文解读 | AI工具如何影响数学建模?从评委和O奖论文出发-O奖论文做对了什么?

模型假设仅仅是简单陈述吗&#xff1f;允许AI的使用是否降低了比赛难度&#xff1f;还在依赖机器学习的模型吗&#xff1f;处理题目的方法有哪些&#xff1f;O奖论文的优点在哪里&#xff1f; 本文调研了当年赛题的评委文章和O奖论文&#xff0c;这些问题都会在文章中一一解答…

C语言练习(17)

两个乒乓球队进行比赛&#xff0c;各出3人。甲队为A、B、C 3人&#xff0c;乙队为X、Y、Z 3人&#xff0c;并抽签决定比赛名单。有人向队员打听比赛的名单&#xff0c;A说他不和X比&#xff0c;C说他不和X、Z比&#xff0c;请编程序找出3对选手的对阵名单。 #include <stdi…

【回忆迷宫——处理方法+DFS】

题目 代码 #include <bits/stdc.h> using namespace std; const int N 250; int g[N][N]; bool vis[N][N]; int dx[4] {0, 0, -1, 1}; int dy[4] {-1, 1, 0, 0}; int nx 999, ny 999, mx, my; int x 101, y 101; //0墙 (1空地 2远方) bool jud(int x, int y) {if…

Flowable 审核功能封装

文章目录 引言I 查询当前用户需要审核的数据列表整体逻辑根据组获取任务数据根据审核人获取任务数据II 进行审核整体逻辑III 审核历史查询IV 流程图查看流程进度思路根据任务 ID 获取任务进度流程图引言 流程引擎功能封装 : 审核列表数据查询进行审核的整体逻辑:获取任务 Id,…

Java-数据结构-二叉树习题(2)

第一题、平衡二叉树 ① 暴力求解法 &#x1f4da; 思路提示&#xff1a; 该题要求我们判断给定的二叉树是否为"平衡二叉树"。 平衡二叉树指&#xff1a;该树所有节点的左右子树的高度相差不超过 1。 也就是说需要我们会求二叉树的高&#xff0c;并且要对节点内所…

github汉化

本文主要讲述了github如何汉化的方法。 目录 问题描述汉化步骤1.打开github&#xff0c;搜索github-chinese2.打开项目&#xff0c;打开README.md3.下载安装脚本管理器3.1 在README.md中往下滑动&#xff0c;找到浏览器与脚本管理器3.2 选择浏览器对应的脚本管理器3.2.1 点击去…

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证8)

为进一步测试通过请求头传递token进行身份验证&#xff0c;在main.htm中增加layui的数据表格组件&#xff0c;并调用后台服务分页显示数据&#xff0c;后台分页查询数据接口如下所示&#xff08;测试时&#xff0c;直接将数据写死到代码中&#xff0c;没有查询数据库&#xff0…

Linux系统 C/C++编程基础——使用make工具和Makefile实现自动编译

ℹ️大家好&#xff0c;我是练小杰&#xff0c;今天周二了&#xff0c;距离除夕只有&#xff16;天了&#xff0c;新的一年就快到了&#x1f606; 本文是有关Linux C/C编程的make和Makefile实现自动编译相关知识点&#xff0c;后续会不断添加相关内容 ~~ 回顾:【Emacs编辑器、G…

68,[8] BUUCTF WEB [RoarCTF 2019]Simple Upload(未写完)

<?php // 声明命名空间&#xff0c;遵循 PSR-4 自动加载规范&#xff0c;命名空间为 Home\Controller namespace Home\Controller;// 导入 Think\Controller 类&#xff0c;以便扩展该类 use Think\Controller;// 定义 IndexController 类&#xff0c;继承自 Think\Control…

可以自己部署的微博 Mastodon

Mastodon&#xff08;又称乳齿象、长毛象或万象&#xff09;是一个自由开源的去中心化的分布式微博客社交网络。它的用户界面和操作方式跟推特&#xff08;Twitter&#xff09;类似&#xff0c;但整个网路并非由单一机构运作&#xff0c;而是以多个由不同营运者独立运作的伺服器…

机器学习-核函数(Kernel Function)

核函数&#xff08;Kernel Function&#xff09;是一种数学函数&#xff0c;主要用于将数据映射到一个更高维的特征空间&#xff0c;以便于在这个新特征空间中更容易找到数据的结构或模式。核函数的主要作用是在不需要显式计算高维特征空间的情况下&#xff0c;通过内积操作来实…

AQS公平锁与非公平锁之源码解析

AQS加锁逻辑 ReentrantLock.lock public void lock() {sync.acquire(1);}AbstractQueuedSynchronizer#acquire public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}addWaiter就是将节点加入…

软件授权产品介绍

CodeMeter技术可提供高达40亿个授权模块&#xff0c;其中6000个可存放于硬件加密狗CmDongle中&#xff0c;其他可存放于软授权CmActLicense中按需激活&#xff0c;CodeMeter云授权CmCloud也可以无任何限制的为“云中软件”提供灵活的授权控制。 CodeMeter安全时钟模块采用了独…

Excel 技巧17 - 如何计算倒计时,并添加该倒计时的数据条(★)

本文讲如何计算倒计时&#xff0c;并添加该倒计时的数据条。 1&#xff0c;如何计算倒计时 这里也要用公式 D3 - TODAY() 显示为下面这个样子的 然后右键该单元格&#xff0c;选 设置单元格格式 然后点 常规 这样就能显示出还书倒计时的日数了。 下拉适用到其他单元格。 2&a…

Vue3初学之Element Plus Dialog对话框,Message组件,MessageBox组件

Dialog的使用&#xff1a; 控制弹窗的显示和隐藏 <template><div><el-button click"dialogVisible true">打开弹窗</el-button><el-dialogv-model"dialogVisible"title"提示"width"30%":before-close&qu…

C++ 类与对象(上)

在C中&#xff0c;在原来C语言基础上引入了类的概念。与C语言最大的不同就是&#xff1a;C可以在类中定义函数。由类声明的变量&#xff0c;称为对象。 1.类的定义 1.1类定义的格式 class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c;…

什么样的问题适合用递归

递归是一种通过函数调用自身来解决问题的方法。递归适用于那些可以被分解为相似子问题的问题&#xff0c;即原问题可以通过解决一个或多个更小规模的同类问题来解决。递归通常需要满足以下两个条件&#xff1a; 递归基&#xff08;Base Case&#xff09;&#xff1a;问题的最简…