Effective Java笔记(16)要在公有类而非公有域中使用访问方法

        有时候,可能需要编写一些退化类,它们没有什么作用,只是用来集中实例域 :

class Point {public double x;public double y;
}

        由于这种类的数据域是可以被直接访问的,这些类没有提供封装( encapsulation )的功能。 如果不改变 API,就无法改变它的数据表示法, 也无法强加任何约束条件;当域被访问的时候,无法采取任何辅助的行动 。 坚持面向对象编程的程序员对这种类深恶痛绝,认为应该用包含私有域和公有访问方法( getter ) 的类代替 。 对于可变的类来说,应该用公有设值方法( setter )的类代替 :

class Point {private double x;private double y;pub1ic Point(double x, double y) {this.x = x;this.y = y;}public double getX() { return x; }public double getY() { return y; }public void setX(double x) { this.x = X; }public void setY(double y) { this.y = y; }
}

        毫无疑问,说到公有类的时候,坚持面向对象编程思想的看法是正确的 : 如果类可以在它所在的包之外进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性 。如果公有类暴露了它的数据域 ,要想在将来改变其内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了 。

        然而 , 如果类是包级私有的,或者是私有的嵌套类, 直接暴露它的数据域并没有本质的错误——假设这些数据域确实描述了该类所提供的抽象 。 无论是在类定义中,还是在使用该类的客户端代码中,这种方法比访问方法的做法更不容易产生视觉混乱 。 虽然客户端代码与该类的内部表示法紧密相连,但是这些代码被限定在包含该类的包中 。 如有必要,也可以不改变包之外的任何代码,而只改变内部数据表示法 。 在私有嵌套类的情况下,改变的作用范围被进一步限制在外围类中 。

        让公有类直接暴露域虽然从来都不是种好办法,但是如果域是不可变的,这种做法的危害就比较小一些 。 如果不改变类的 API ,就无法改变这种类的表示法,当域被读取的时候,你也无法采取辅助的行动,但是可以强加约束条件 。 例如,这个类确保了每个实例都表示一个有效的时间:

public final class Time {private static final int HOURS_PER_DAY = 24;private static final int MINUTES_PER_HOUR = 60;public final int hour;public final int minute;public Time(int hour, int minute) {if (hour < 0 || hour >= HOURS_PER_DAY)throw new IllegalArgumentException("Hour: " + hour);if (minute < 0 || minute >= MINUTES_PER_HOUR)throw new IllegalArgumentException("Min:"+ minute);this.hour = hour;this.minute = minute;}... // Remainder omitted
}

        简而言之,公有类永远都不应该暴露可变的域 。 虽然还是有问题,但是让公有类暴露不可变的域,其危害相对来说比较小 。 但有时候会需要用包级私有的或者私有的嵌套类来暴露域,无论这个类是可变的还是不可变的 。

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

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

相关文章

探索 Scikit-learn:Python 机器学习初级篇

Scikit-learn 是 Python 中最著名的机器学习库之一&#xff0c;它提供了大量实用的机器学习算法以及相关的工具&#xff0c;可以方便我们进行数据挖掘和数据分析。在这篇文章中&#xff0c;我们将介绍 Scikit-learn 的基本使用&#xff0c;包括如何导入数据、预处理数据、选择和…

Twisted Circuit

题目描述 输入格式 The input consists of four lines, each line containing a single digit 0 or 1. 输出格式 Output a single digit, 0 or 1. 题意翻译 读入四个整数 00 或者 11&#xff0c;作为如图所示的电路图的输入。请输出按照电路图运算后的结果。 感谢PC_DOS …

时序预测 | MATLAB实现Hamilton滤波AR时间序列预测

时序预测 | MATLAB实现Hamilton滤波AR时间序列预测 目录 时序预测 | MATLAB实现Hamilton滤波AR时间序列预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 预测在很大程度上取决于适合周期的模型和所采用的预测方法,就像它们依赖于过滤器提取的周期一样。标准 Hodrick-P…

Python教程(4)——Python开发工具PyCharm的下载与安装

PyCharm是一种专业的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司开发和维护。它提供了丰富的功能和工具&#xff0c;帮助开发人员更高效地编写、调试和测试Python代码。如果是一些大型Python项目强烈推荐用这个来开发。今天我们来介绍一下PyCha…

nginx系列第八篇:Ubuntu下验证nginx各请求处理阶段

Nginx处理请求的过程一共划分为11个阶段&#xff0c;按照执行顺序依次是 post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log。 准备工作&#xff1a;host文件加入测试域名 sudo vi /etc/hosts 加入…

matlab: cell合并/拼接 数组/array/matrix 去重

1. cell合并/拼接 字符串、向量、矩阵、cell数组拼接 cell1{[1,1],[2,1,1]}; cell2{[2,2],[2,1,1,5]}; res[cell1,cell2];%列拼接 res[cell1;cell2];%行拼接2. 数组/array/matrix 去重 数组或矩阵中的去除重复元素 另参考 string比较 % 第一种方法 r_integer [1,3,2,2,2,…

C语言--程序环境和预处理

翻译环境 C语言的代码是文本信息&#xff0c;对于计算机来说无法直接理解&#xff0c;需要通过翻译环境进行翻译成二进制信息&#xff1b; 我们在写代码的时候&#xff0c;一般都会写在一个源文件中&#xff0c;这时候我们就使用我们的编译器(VS)将其转换为机器代码&#xff0…

Android应用启动全流程分析(源码深度剖析)

作者&#xff1a;努比亚技术团队 源码来源&#xff1a;努比亚技术团队 1.前言 从用户手指点击桌面上的应用图标到屏幕上显示出应用主Activity界面而完成应用启动&#xff0c;快的话往往都不需要一秒钟&#xff0c;但是这整个过程却是十分复杂的&#xff0c;其中涉及了Android系…

TortoiseGit 入门指南13:拣选

对于多分支的代码库&#xff0c;将代码从一个分支转移到另一个分支是常见需求。 这时分两种情况。一种情况是&#xff0c;你需要另一个分支的所有代码变动&#xff0c;那么就采用 合并&#xff08;merge&#xff09;。另一种情况是&#xff0c;你只需要部分代码变动&#xff0…

Android 11以下DialogFragment里弹出PopWindow显示问题

最近在写UI的时候发现一个非常有意思的事情&#xff0c;Android 11以下在DialogFragment里面弹出PopWindow&#xff0c;最终会被截取。 尝试过一些方法以后将解决方案做一个记录&#xff1a; mPopWindow.setClippingEnabled(false); 应该是Android 11后这里默认设置成了true…

Rust学习-构建命令行程序

Rust 的运行速度、安全性、单二进制文件输出和跨平台支持使其成为创建命令行程序的绝佳选择 本文以实现一个minigrep为例&#xff0c;展开对之前学习的回归 初版 接收命令行参数并打印文件内容 // 当所需函数嵌套了多于一层模块时&#xff0c;通常将父模块引入作用域 // std…

[JVM] 2. 类加载子系统(1)-- 内存结构、类加载子系统概述

一、内存结构 类加载子系统的职责是&#xff1a;加载class文件到内存中。 完整的内存结构如下&#xff1a; 二、类加载过程 类加载过程总体分为Loading&#xff08;加载&#xff09;、Linking&#xff08;链接&#xff09;、Initialization&#xff08;初始化&#xff09;三…

Mars3d采用ellipsoid球实现模拟地球旋转效果

1.Mars3d采用ellipsoid球实现模拟地球旋转效果 2.开始自选装之后&#xff0c;模型一直闪烁 http://mars3d.cn/editor-vue.html?idgraphic/entity/ellipsoid 3.相关代码&#xff1a; import * as mars3d from "mars3d"export let map // mars3d.Map三维地图对象 …

深入浅出如何通过API瞬间搭建亿万商品外贸代购系统PHP系统

什么是淘宝代购 淘宝代购是近年兴起的一种购物模式&#xff0c;是帮国外客户购买中国商品。主要是通过万邦 科技的外贸代购系统&#xff0c;把淘宝、天猫等电商平台的全站商品通过API 接入到你的网站 上&#xff0c;瞬间就可以架设一个有数亿产品的大型网上商城&#xff0c;而…

2023年测试之路,从功能测试进阶测试开发工程师,突破内卷...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试开发工程师到…

Redis可视化工具(Redis Desktop Manager)

redis是我们平时开发工作中经常用到的非关系型数据库&#xff0c;常用于做数据缓存&#xff0c;分布式锁等。 为了更方便的使用redi&#xff0c;这里给大家推荐一款可视化工具&#xff1a;Redis Desktop Manager。 1.下载与安装 直接到gihub下载&#xff0c;地址 Release 0.…

剑指 Offer 59 - I. 滑动窗口的最大值

题目介绍 给定一个数组 nums 和滑动窗口的大小 k&#xff0c;请找出所有滑动窗口里的最大值。 示例: 输入: nums [1,3,-1,-3,5,3,6,7], 和 k 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 …

uni-app的H5版本下载跨域问题

前端能正常访问图片&#xff0c;但无法下载 因为路径不经过业务代码&#xff0c;所以需要在nginx配置跨域 代码&#xff1a; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods GET, POST, OPTIONS; add_header Access-Control-Allow-H…

基于simulink的DPLL仿真笔记

该笔记主要用于本人思路整理与记录 本设计运用的是电荷泵一阶环路滤波器&#xff0c;二阶三阶则在此基础上举一反三&#xff0c;以后如有机会会慢慢补全 文章目录 一.仿真模型PS&#xff08;题外话&#xff09; 二.仿真结果三.环路滤波器分析1. 环路滤波器对比LPF2. 环路滤波器…

Shikra:新一代多模态大语言模型,理解指向,说出坐标

“ Shikra&#xff1a;解锁多模态语言模型参考对话的魔法” Shikra和用户的对话案例 在人类的日常交流中&#xff0c;经常会关注场景中的不同区域或物体&#xff0c;双方都可以通过说话并指向这些区域来进行高效的信息交换。我们将这种对话模式称为参考对话&#xff08;Referen…