java - 使用 getter 和 setter 调用实例属性好不好?
问题描述
我正在制作一个战舰 java 游戏,在整个过程中,我使用 Point 类来存储 X 和 Y 坐标。我知道 getter 和 setter 是如何工作的以及我们为什么使用它们,但是这个特定的类同时具有 getter 和 public 属性所以这是我的问题,使用什么会更好?
px 或 p.getX()
我知道使用吸气剂是一个好习惯,但在这种情况下我很困惑,我应该使用什么?
解决方案
(回顾一下,这是关于不可变对象与直接更改原始位置值)
我必须反驳@rzwitserloot 的回答。他提供了三个有问题的课程:
- 第一个,Lombok 的,要么也是不可变的,要么使用 @NonFinal 或 @PackagePrivate 注释,因此使用(创建/允许)未检查的 getter 和 setter。因此,当谈到代码的安全性时,要么存在不可变性的问题,要么与(可直接访问的)公共成员变量处于同一级别。
- 第二个,记录,是浅不可变的。这意味着对位置的任何更改都不能对 Point 本身进行,但每次都必须创建一个新的 Point 实例
- 第三个,与第二个非常相似,是一个真正不可变的类。此处相同:对位置的任何更改都不能对 Point 本身进行,但每次都必须创建 Point 的新实例
所以我们在这里看到的是:不变性。如果你想让你的代码保持整洁,不变性很好。尤其是调试。不变性是编写干净软件的好工具。修补匠的梦想。但是对于动手操作的人,在某些情况下,这很快就会变成“过度工程”。
但在性能方面存在一些问题:
- 对于不可变类的每次更改,您都必须创建该类的副本,并进行一些更改
- 更难只更改一个方面/值,然后再更改另一个值,而不创建多个对象
所以,假设一个愚蠢的JVM,
- 由于您需要创建所有这些对象,您很快就会遇到基于内存的性能问题
- 速度比简单地更改值要慢得多。
很高兴,JVM 非常聪明:
- 在短暂的运行时间之后,JIT 会发现/知道使用和丢弃的类并对其进行优化。
- 此外,通过 getter/setter 的访问速度要慢得多,但 JVM 在大多数情况下也可以消除其中的大部分。
此外,随着 JVM 每年的进步,优化/速度可能会进一步提高,从而减少甚至消除不可变类的任何缺点。此外,优化肯定会更安全,或者至少与您可以设计的任何东西一样安全。但它们能有效率吗?
但也有 JVM 不能做任何优化的情况。尤其是当涉及接口/抽象基类时,即使是方法调用也会变慢,因为真正的目标方法的地址必须在运行时每次解析。
所以最后,由你来测试和决定你想使用什么方法。如果这一点增加的安全性真的值得性能的“下降”。以及您对 JVM 优化的未来期望有多少。
其他人是对的:除非您真的在使用 AWT,否则不要使用 AWT 类。最好有自己的课程,以满足您的需求。
//大更新:
最后一件事要考虑,IMO 使用不可变 Position 类型的最大缺点是:
(警告:这个例子会变得越来越荒谬!但它显示了该策略的方向)
- 假设我们有以下类:
class Ship { Position position; }
- 所以我们通过
ship.position
- 现在,当我们想改变船的位置时,我们必须改变对位置的引用:
ship.position = ... (new Position or ship.position.clone(newX,newY) or ship.position.with(newX,newY)
- 所以每当我们想改变船的位置,并遵循不变性模式
-
- 半结果:我们至少需要另一个 getter/setter 作为 Position in Ship
-
-
- 任何使用位置的东西都必须知道它包含的类,例如 Ship 以及任何和所有其他具有位置并且可能由相同逻辑计算的东西(是的,接口,但它在哪里停止?)
-
-
-
- 此外,如果 Ship.position 不为空,您每次都必须检查......
-
-
- 完全因此:船舶也应该是不可变的,并且在其位置或任何其他状态发生任何变化时,场景中的船舶将被一个静音的不可变副本替换。
-
-
- 此外,任何更改都必须替换场景。哇。
-
-
-
-
- 任何与船一起工作的东西都必须知道所有对船的引用,所以它可以更新那些
-
-
-
-
-
- 如果场景发生变化,游戏也应该是不可变的,并且它的实例必须被替换..等等,什么?
-
-
-
-
- 所以我们看到存在很多不可变对象不是一个好的解决方案的场景
-
推荐阅读
- azure - 为什么 Chrome 允许此静默 Azure OAuth 授权请求,但不允许 Firefox 和 Edge?
- javascript - 如何在 for 循环中等待异步查询完成?
- javascript - 动态添加字段并计算总和
- ffmpeg - FFmpeg:覆盖 GIF 旋转和缩放
- lua - 使用自定义 lua/luajit 重载/注入已编译程序的 lua 运行时
- jquery - 当 .html 函数添加输入时,输入不会向 FORM 添加值
- python - 在 for 循环中动态创建变量
- python - 使用 chromedriver 从 Selenium 打印 PDF
- javascript - 如何解决模拟函数中的 Promise?
- java - 响应不是来自使用改造 2 的服务器