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

DeepSeek + 番茄小说:AI辅助小说开发最全指南 DeepSeek与番茄小说合作推出AI辅助小说创作系统,通过DeepSeek的文本生成能力(包括情节构建、角色塑造等)结合番茄小说的市场数据,为作者提供从创意到发布的全流程支持。系统包含智能创意生成器、角色设计、章节自动生成等核心模块,采用数据驱动优化策略,支持128K长文本处理和多风格模仿。开发架构采用Python+FastAPI技术栈,提供分层审核机制确保质量。该系统可帮助作者突破创作瓶颈,提升效率,同时提供订阅制、内容分成等多元变现模式。需注意版权问题和原创性保证。 阅读详情

在公有类中使用访问方法而非公有域

在面向对象编程中的封装原则(encapsulation)强调,类的实现细节应该对外界隐藏,而只通过控制良好的接口进行交互。这条规则同样适用于类的成员变量(域):不要暴露公共域,而是通过访问方法(getter 和 setter)进行操作。这种方法有助于实现封装、提高代码的灵活性和可维护性、降低耦合。


1. 为什么公有类中不应使用公有域?

1.1 暴露内部实现细节

如果直接使用公有域,外界代码会直接访问或修改类的成员变量,其使用方式可能依赖这些变量的当前实现。一旦你需要修改类的实现(比如改变成员变量的结构或语义),就会破坏依赖这些字段的代码。

例子:

public class Point {
    public int x; // 公共域
    public int y;
}

此时,外界可以直接访问并修改 Point 的内容:

Point p = new Point();
p.x = 10; // 直接操作
p.y = 20;

如果有一天你需要用极坐标来表示 Point(使用 radius 和 theta 替代 x 和 y),你将不可能对其进行修改,因为外界代码严重依赖 x 和 y。

1.2 难以添加限制和验证逻辑

直接对公共域赋值,无法限制赋值的合法性或加入额外的验证逻辑。

例子:
假设你希望 Point 的 x 和 y 坐标始终为非负数,直接使用公共域将无法实现此约束:

Point p = new Point();
p.x = -10; // 无法阻止非法赋值
1.3 打破封装,导致不可维护

如果成员变量是公开的,外部代码甚至可能直接修改该变量为非法的状态(即使它对于类而言是不一致或不安全的)。这打破了封装原则,降低了类的维护性。


2. 使用访问方法的好处

更推荐的做法是将类的成员变量声明为私有(private),并提供公有的访问方法(getter 和 setter)来控制对这些变量的访问和修改。访问方法可以提供以下好处:

2.1 提供灵活性:隐藏实现细节

通过访问方法,可以对外暴露一种“接口化”的行为,而隐藏变量的实际实现方式。即使将来更改变量的存储方式,访问方法也可以保持接口稳定。

改进的实现:

public class Point {
    private int x; // 私有变量
    private int y;

    // Getter 方法
    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    // Setter 方法
    public void setX(int x) {
        if (x < 0) { // 添加合法性校验
            throw new IllegalArgumentException("x must be non-negative");
        }
        this.x = x;
    }

    public void setY(int y) {
        if (y < 0) {
            throw new IllegalArgumentException("y must be non-negative");
        }
        this.y = y;
    }
}

即使未来 Point 从笛卡尔坐标改为极坐标表示(radius 和 theta),仍然可以通过 getter 和 setter 提供不变的 getX() 和 getY() 接口,从而保证外界代码不受影响。

2.2 支持验证逻辑和额外行为

访问方法可以在读取或写入数据时执行合法性检查、数据转换等操作,而直接暴露公共域就不能做到这一点。

改进后:

public class Temperature {
    private double celsius; // 温度以摄氏为内部存储单位

    // Getter:以摄氏为单位返回温度
    public double getCelsius() {
        return celsius;
    }

    // Setter:合法性校验
    public void setCelsius(double celsius) {
        if (celsius < -273.15) { // 合法性校验:避免低于绝对零度
            throw new IllegalArgumentException("Temperature cannot be below absolute zero");
        }
        this.celsius = celsius;
    }

    // 额外 Getter:以华氏为单位返回温度
    public double getFahrenheit() {
        return celsius * 9 / 5 + 32;
    }

    // 额外 Setter:接收以华氏为单位的温度
    public void setFahrenheit(double fahrenheit) {
        setCelsius((fahrenheit - 32) * 5 / 9);
    }
}

优势:
外界可以以摄氏或华氏为单位使用 Temperature 类,而类内部始终以摄氏存储温度值。

2.3 提高类的易维护性和安全性

将数据的内部表示与访问方式解耦,如果未来修改了内部逻辑或存储方式,只需调整访问器方法,而无需修改客户端代码。这种封装可以让类更加容易维护。

2.4 支持只读或条件性访问

访问方法提供更好的权限控制。例如,可以通过只提供 getter 不提供 setter 来实现只读字段;或者根据上下文条件决定访问权限。

示例:只读成员

public class Circle {
    private final double radius; // 半径

    public Circle(double radius) {
        if (radius <= 0) {
            throw new IllegalArgumentException("Radius must be positive");
        }
        this.radius = radius;
    }

    public double getRadius() { // 仅提供 getter
        return radius;
    }
}

示例:条件性访问

public class Account {
    private double balance;

    public Account(double initialBalance) {
        this.balance = initialBalance;
    }

    public double getBalance(User user) {
        if (!user.hasPermission("VIEW_BALANCE")) {
            throw new SecurityException("User does not have permission to view balance");
        }
        return balance;
    }
}

3. 使用访问方法的注意事项

3.1 避免滥用访问方法

虽然访问方法是一个好的设计实践,但并非所有字段都需要访问方法。只用当字段需要与外界交互时,才需要提供访问器(getter/setter)。否则,保持字段为私有并在类内部管理即可。

3.2 不要过度细化访问方法

访问方法应该符合逻辑需求,而不是一味为所有字段都添加 getter 和 setter。这可能会导致不必要的代码膨胀。

3.3 final 字段与访问方法

当字段确实应该不可变时,可以将其声明为 final,且仅提供 getter。


4. 书中案例

原始问题:直接暴露数组

在《Effective Java》中提到了一个常见问题:用 public 数组暴露类的内部数据。

public class Test {
    public static final String[] VALUES = {"a", "b", "c"}; // 直接暴露
}

问题:外部代码可以通过引用直接修改 VALUES 的内容:

Test.VALUES[0] = "z"; // 修改了内部数组
解决:通过访问方法返回副本

通过访问器返回数组的副本,使得外界不能直接修改 VALUES:

public class Test {
    private static final String[] VALUES = {"a", "b", "c"};

    public static String[] getValues() {
        return VALUES.clone(); // 返回副本
    }
}

这样,外界修改副本时不会影响原数组:

String[] valuesCopy = Test.getValues();
valuesCopy[0] = "z"; // 不影响原数组

5. 总结

  • 封装的核心原则是:将实现隐藏,暴露必要的功能接口。
  • 禁止直接暴露公有域,应使用访问方法(getter 和 setter)来操作私有字段。
  • 使用访问方法的优点包括:
    1. 隐藏实现细节,提高灵活性。
    2. 支持数据校验、转换等附加逻辑。
    3. 提高代码的可维护性,易于以后扩展。
    4. 防止外界直接修改类的内部状态,保证数据一致性。
强化学习在视觉导航中的应用 强化学习在视觉导航中的应用​ ,人工智能,计算机视觉,大模型,AI,强化学习(Reinforcement Learning, RL)是一种通过智能体(Agent)与环境进行交互,以最大化累积奖励为目标的机器学习范式。它不依赖于预定义的规则或大量标注数据,而是让智能体在试错过程中学习最优策略。计算机视觉(Computer Vision)则赋予智能体 “观察” 环境的能力,使其能够从图像或视频中提取有用信息。 阅读详情

相关推荐

Android逆向实战:用Xposed Hook微信消息发送(附完整代码)

本文提供了一份Android逆向实战指南,详细讲解如何使用Xposed框架Hook微信消息发送功能。内容涵盖环境搭建、逆向分析定位关键方法、编写Hook模块代码以及调试部署的全过程,并附有完整代码示例,帮助开发者深入理解Android应用底层交互与Hook技术。

weixin_29196315的博客 1118

要在公有类而非公有域中使用访问方法——《effective Java》第三版

毫无疑问,说到公有类的时候,坚持面向对象编程思想的看法是正确的:如果类可以在它所在的包之外进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。如果公有类暴露了它的数据域,要想在将来改变其内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了。 然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误——假设这些数据域确实描述了该类所提供的抽象。无论是在类定义中,还是在使用该类的客户端代码中,这种方法比访问方法的做法更不容易产生视觉...

m0_65546127的博客 676

同花顺 python量化交易_开启量化第一步!同花顺iFinD数据接口免费版简易操作教程...

来源:雪球App,作者: 同花顺-iFinD,(https://xueqiu.com/6706494343/141951051)金融市场波动频繁,投资往往会夹杂非理性的情绪。而量化交易,旨在以先进的数学模型替代人为的主观判断,利用计算机技术从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略,辅助投资者进行理性投资。不过计算机分析存在一定的技术门槛,有没有简单易学的量化交易方式,能够...

weixin_35911805的博客 2万+

《Effective Java》阅读笔记 14在公有类中使用访问方法而非公有域

1.问题 class Point { public double x; public double y;} } 如果直接将类中的域暴露为共有域,那么你将失去这个域的控制权。如果你以后想要在类中记录x被赋值了多少次和被获取了多少次,你将无法做到,因为你根本不知道它什么时候在外部被获取,什么时候再外部被赋值。 2.解决办法 class Point { private double x; private double y; public Point(double x, d

weixin_41563161的博客 230

SRAM compiler中Power Gating与Retention的实战配置指南

本文深入解析了在SRAM compiler中配置Power Gating(电源门控)与Retention(数据保持)功能的实战指南。针对低功耗芯片设计,文章详细阐述了如何根据应用场景(如移动AP、IoT设备)权衡开关类型、尺寸、唤醒时序以及保持电压,以实现静态功耗优化与数据可靠性的最佳平衡,并强调了后端实现与签核检查的关键要点。

weixin_29204121的博客 296

QMI8658姿态传感器实战:从校准到自检的完整避坑指南

本文详细解析了QMI8658姿态传感器的校准与自检流程,提供了从硬件环境搭建到高级功能开发的完整避坑指南。通过真实案例揭示电源设计、接口优化、温度补偿等关键细节,帮助开发者提升传感器精度和可靠性,适用于工业级应用场景。

weixin_29184075的博客 455

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

无论是在类定义中,还是在使用该类的客户端代码中,这种方法比访问方法的做法更不容易产生视觉混乱。让公有类直接暴露域虽然从来都不是种好办法,但是如果域是不可变的,这种做法的危害就比较小一些。如果不改变类的 API ,就无法改变这种类的表示法,当域被读取的时候,你也无法采取辅助的行动,但是可以强加约束条件。但有时候会需要用包级私有的或者私有的嵌套类来暴露域,无论这个类是可变的还是不可变的。如果公有类暴露了它的数据域 ,要想在将来改变其内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了。

琅琊之榜 285

Python - 多页pdf 合称为一页

尝试使用 ReportLab 来重画 pdf,但探索起来有点麻烦。重要的是解决手头这个问题,所以就算方法蠢,但简单完事。以下生成结果,最有一页 pdf 可能会显示在第一页,手动编辑下 pdf 即可;或者你也可以修改代码逻辑来完善。打印ppt,一页占用A4纸比较浪费,想多页合成一个 A4大小;安装 fitz,单独安装 fitz 使用可能会报错。将 PDF 拆分为 图片来保存。

AI工程化、开源分享、文档翻译、代码笔记 1425

Effective Java笔记第三章类和接口第二节在公有类中使用访问方法而非公有域

Effective Java笔记第三章类和接口 第二节在公有类中使用访问方法而非公有域 1.有时候可能会编写一些退化类,没什么作用,只是用来集中实例域,比如说: class Point { public double x; public double y; } 由于这种类的数据可以被直接访问,这些类没有提供封装的功能。如果不改变API,就无法改变它的数据表示法,也无法强加任何约束条件,当域被访问的时候,无法采取任何辅助行动。这是不可取的,对于可变的类来说,应该用包含私有

zh123456_789的博客 181

Openclaw第3章:进阶部署

本章面向需要在特定环境中稳定运行 OpenClaw 的用户,介绍 Windows、Linux、Docker 以及 Cloudflare Workers 四种进阶部署方式。每种方式各有侧重:Windows 部署适合桌面用户日常使用,Linux 部署适合开发者,Docker 部署适合追求环境隔离的运维场景,Cloudflare Workers 部署则适合希望获得全球边缘网络加速的用户。读者可根据自身环境和需求选择合适的方案,完成本章后可继续阅读第4章了解维护升级流程。

Maynor的博客 1295

OpenClaw(Clawdbot/Moltbot)如何正确的配置浏览器,实现对浏览器的自动化操作功能(浏览器状态为running:false怎么办)

OpenClaw(Clawdbot/Moltbot)浏览器自动化功能无效?🤖 本文详细介绍如何解决这个问题🔧,让你的OpenClaw(Clawdbot/Moltbot)真正具备"睁眼看世界"的能力,支持网页搜索、点击操作和截图等功能 ✅

XiaoqiangClub的博客 8109

Effective Java 第二版 中文版 笔记(十四)在公有类中使用访问方法而非公有域

这本书中有很烦人的一点,他的定义的官方话看不懂啊? 域就是类中的成员变量,有时也叫字段,属性都是同一个意思。公有域就是能在其它类中直接访问的域,也就是带有域。 这就很容易明白了 class Test { private int a; // 这是一个私有域,只能在本类访问 public int b; // 这就是一个公有域了,可以在其它类中直接访问 ...

qq_37538698的博客 211

概率的接力:拆解大模型“预测下一个词“的底层逻辑

大模型的智能不在于它拥有了意识,而在于它用纯数学的架构,将人类语言的复杂结构压缩为可计算的向量轨迹与概率接力。当我们不再将其拟人化为"思考者",而是视作高维条件概率引擎时,才能真正驾驭它。预测下一个词,从来不是终点,而是起点。未来的核心竞争力,属于那些能洞察其统计本质、善用其模式生成能力,并以人类理性与事实为锚点的协作者。词元的轨迹终会止步于上下文窗口,但对技术底层的清醒认知,才是跨越幻觉、走向真实智能的基石。

AI浩 330

要在公有类而非公有域中使用访问方法《Effective java第四章第十六条 》

对 Effective java第四章第十六条 要在公有类而非公有域中使用访问方法 进行学习

qq_47129343的博客 973

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

跟我学(Effective Java 2)第14条:在公有类中使用访问方法而非公有域

第14条:在公有类中使用访问方法而非公有域 有时候、可能会编写一些退化类(degenerate classes),没有什么作用,只是用来集中实例域: class Point { public double x; public double y; } 由于这种类的数据是可以直接被访问的,这些类没有提供封装(encapsulation)的功能。如果不改变API,就无法改变它的数据表...

Dullon_jiang的博客 262

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

《Effective Java》第16条:要在公有类而非公有域中使用访问方法

原文P63:然而,如果类是包级私有的,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误。比如一个人(user),他的名字,年龄,性别,都是他的私有属性。所以:原文P63:毫无疑问,说到公有类的时候,坚持面向对象编程思想的看法是正确的:如果类可以在它所在的包之外进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。这种源码不值得效仿。书中最后给的例子(Time类),说明了,如果一个域是final的,那么将final域设置为public的,这种危害相对于小一些,但是这种做法依然是不提倡的!

TD_FAlmK的博客 397

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Effective Java 类和接口 14.在公有类中使用访问方法而非公有域

一位学习C语言(那种C语言不太清楚)的同事问我,为什么类.属性可以解决的事情,为什么要get与set方法,当时我懵了。如下:class Point{ public double x; public double y; }调用:Point p=new Point(); p.x=10; p.y=20; double x=p.x; double y=

yancyang的博客 1万+

Effective Java 在公有类中使用访问 方法而非公有域

Class Point { public double x; public double y; } 如上面Point类的数据域是可以直接被访问的,这样的类没有提供封装。如果不改变API,就无法改变它的数据表示法(比如,使用一个比double更高精度的类来表示x和y),也无法强加任何约束条件(比如以后我们可能会希望x和y不会超过某个值)。 Class Point { private double x; private double y; public..

菜园子丶For丨丶Tomorrow的博客 151

effective java-类和接口_effective java 类,零基础入门到精通,收藏这篇就够了

本部分总结effective java第四章类和接口的内容。

leah126的博客 1034

Effective Java 第14条:在公有类中使用访问方法而非公有域

转载: http://yanfeichening.iteye.com/blog/1497657 如果类可以在它所在包的外部进行访问,就提供访问方法。 如果类是包私有的,或者私有的嵌套类,直接暴露它的数据域并没有本质的错误。 总之,公有类永远都不应该暴露可变的域。虽然还是有几个问题,但是让公有类暴露不可变的域,危害比较小。但是,有时候需要会用到包级私有的或者私有的嵌套类

Come on ! Just Do it ! 2634

effective java(14) 之在公有类中使用访问方法而非公有域

effective java 之在公有类中使用访问方法而非公有域 1、如何理解这句话: 我们不能这样做, Class Point { public double x; public double y; } Point类的数据域是可以直接被访问的,这样的类没有提供封装。 如果不改变API,就无法改变它的数据表示法(比如,使用一个比double更高精度的类来表示x和y),也

Eric的博客 358

《Effective Java》第16条:要在仅有类中使用访问方法而非公有域

简而言之,公有类永远都不应该暴露可变的域。

ln_ydc的专栏 193

Effective Java之在公有类中使用访问方法而非公有域(十四)

1.对于公有类来说,如果类可以在它所在的包的外部进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性。 如果公有域暴露了他的数据域,要想在将来改变它的内部表示法是不可能的,因为公有类的客户端代码已经遍布各处了。2.如果类是包级私有或者是私有的嵌套类时,直接暴露数据域是没有本质错误的,原因是包级私有或者是私有的嵌套类时,并不会把api暴露在外面,所以将来改变其内部表示法,并不会对客户端产

heihei 255

Effective Java 读书笔记(三):类和接口

使类和成员的可访问性最小化 在公有类中使用访问方法而非公有域 使可变性最小化 复合优先于继承 要么为继承而设计并提供文档说明要么禁止继承 接口优于抽象类 接口只用于定义类型 类层次优于标签类 用函数对象表示策略

albon arith 732

effective java读书笔记 (二)

第四章 类和接口 第十三条  使类和成员的可访问性最小化 信息隐藏(封装):设计模块时把它的API与它的实现清晰地隔离开来 封装的带来的好处:有效地接触组成系统的各模块之间的耦合,同时减轻了维护的负担,并且可以有效地调节性能,还可以提高软件的可重用性,也降低了构建大型系统的风险。 java中提供的协助信息隐藏的机制:访问控制机制决定了类、接口和成员的可访问性。对于顶层(非嵌套的)的类和接口

A20090306的专栏 787

《Effective Java》第4章 类和接口

类和接口是Java程序设计语言的核心,那么类和接口的设计上必然会有一些大师的指导性原则,能够指导我们设计出有用,健壮和灵活的类和接口。

AnnaLoad的专栏 674
上一篇: Effective Java笔记:使类和成员的可访问性最小化
下一篇: Effective Java笔记:使可变性最小化
Jooou
博客等级 码龄9年 226粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值