是否总是使用get和set方法来访问类自己的成员字段?

Pab*_*jim 8 java anti-patterns

在Java类中,使用getter和setter访问成员字段是不是很好或者不好?

比如哪个更好:

public Order {
    private Agreement agreement;

    public Agreement getAgreement() {
    return agreement;
    } 

    public void process() {
       //should I use:
       getAgreement().doSomething();
       //Or:
       agreement.doSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

一般来说,我认为直接访问该字段最好是由于KISS原则,并且有人可能会在以后使用不可预测的结果覆盖get方法.

然而,我的同事认为保留一层抽象更好.对此有何共识?

Zac*_*ray 9

老实说,在我看来,这取决于你使用它的原因.就个人而言,如果有疑问,我总是在那里留下额外的抽象级别,以防我以后需要在子类中覆盖它.很多时候,我只是因为我让一个吸气剂或者一个二传手打开而无法改写课程,从而避免了重写课程的痛苦.

另一件事是其他客户端/程序员可能需要以您尚未想到的方式使用您的类,例如,将Agreement类从数据库中拉出来.在这种情况下,当他们覆盖你的类时,你已经让他们(或者可能是你的未来)无法修改数据的检索方式.

因此,除非您完全确定只有一种方法可以访问该字段,并且它是100%直接的,所以最好将值的检索和修改分离,以便在将来某一点上您可以避免重写困难.


Jhe*_*ico 8

这里的核心问题是直接字段访问不适合通过子类重写方法,AOP,动态代理等进行拦截.根据具体情况,这可能是好事也可能是坏事.我会说在内部使用getter和setter不是反模式或模式.根据情况和班级设计,这是好事还是坏事.


And*_*are 7

我认为类的公共接口表示围绕状态的封装,因此即使该类的其他工作也受益于该封装.

如果你在一个公共get方法中包装了一个字段,那么你就有这样做的原因.也许在该方法中存在惰性加载字段或提供审计跟踪的逻辑.无论该方法的原因是什么,您的班级也很可能也需要这种逻辑.

  • 我在使用Hibernate for ORM时遇到过这个问题.直接使用变量的代码总是获取空值,使用getter的代码始终有效.Hibernate提供了一个代理类来支持延迟加载. (2认同)