首页 > 解决方案 > 使用 getter 和 setter 调用实例属性好不好?

问题描述

我正在制作一个战舰 java 游戏,在整个过程中,我使用 Point 类来存储 X 和 Y 坐标。我知道 getter 和 setter 是如何工作的以及我们为什么使用它们,但是这个特定的类同时具有 getter 和 public 属性所以这是我的问题,使用什么会更好?

px 或 p.getX()

我知道使用吸气剂是一个好习惯,但在这种情况下我很困惑,我应该使用什么?

标签: javaencapsulation

解决方案


(回顾一下,这是关于不可变对象与直接更改原始位置值)

我必须反驳@rzwitserloot 的回答。他提供了三个有问题的课程:

  1. 第一个,Lombok 的,要么也是不可变的,要么使用 @NonFinal 或 @PackagePrivate 注释,因此使用(创建/允许)未检查的 getter 和 setter。因此,当谈到代码的安全性时,要么存在不可变性的问题,要么与(可直接访问的)公共成员变量处于同一级别。
  2. 第二个,记录,是浅不可变的。这意味着对位置的任何更改都不能对 Point 本身进行,但每次都必须创建一个新的 Point 实例
  3. 第三个,与第二个非常相似,是一个真正不可变的类。此处相同:对位置的任何更改都不能对 Point 本身进行,但每次都必须创建 Point 的新实例

所以我们在这里看到的是:不变性。如果你想让你的代码保持整洁,不变性很好。尤其是调试。不变性是编写干净软件的好工具。修补匠的梦想。但是对于动手操作的人,在某些情况下,这很快就会变成“过度工程”。

但在性能方面存在一些问题:

  1. 对于不可变类的每次更改,您都必须创建该类的副本,并进行一些更改
  2. 更难只更改一个方面/值,然后再更改另一个值,而不创建多个对象

所以,假设一个愚蠢的JVM,

  1. 由于您需要创建所有这些对象,您很快就会遇到基于内存的性能问题
  2. 速度比简单地更改值要慢得多。

很高兴,JVM 非常聪明:

  1. 在短暂的运行时间之后,JIT 会发现/知道使用和丢弃的类并对其进行优化。
  2. 此外,通过 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 不为空,您每次都必须检查......
    • 完全因此:船舶也应该是不可变的,并且在其位置或任何其他状态发生任何变化时,场景中的船舶将被一个静音的不可变副本替换。
      • 此外,任何更改都必须替换场景。哇。
        • 任何与船一起工作的东西都必须知道所有对船的引用,所以它可以更新那些
        • 如果场景发生变化,游戏也应该是不可变的,并且它的实例必须被替换..等等,什么?
      • 所以我们看到存在很多不可变对象不是一个好的解决方案的场景

推荐阅读