Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 是否通常认为更改对象是一种不好的做法';通过它的getter方法,它的状态是什么?_Java_Getter Setter_Object Composition - Fatal编程技术网

Java 是否通常认为更改对象是一种不好的做法';通过它的getter方法,它的状态是什么?

Java 是否通常认为更改对象是一种不好的做法';通过它的getter方法,它的状态是什么?,java,getter-setter,object-composition,Java,Getter Setter,Object Composition,在我过去的发展过程中,我一直在思考这个问题 我有点反对这样做,我通常会声明一个单独的方法来显式处理逻辑 例如 如果一个类有一个返回对象列表的方法,我认为直接通过它的getter方法修改这个集合是个坏主意 Public Class ReportGenerator{ private List<Configurations> configurations; List<Configuration> getConfigurations (){ re

在我过去的发展过程中,我一直在思考这个问题

我有点反对这样做,我通常会声明一个单独的方法来显式处理逻辑

例如

如果一个类有一个返回对象列表的方法,我认为直接通过它的getter方法修改这个集合是个坏主意

 Public Class ReportGenerator{

    private List<Configurations> configurations;

    List<Configuration> getConfigurations (){
      return this.configurations;
    }

    }
我将使用以下方法:

 Public Class ReportGenerator{

            private List<Configurations> configurations;

          public  List<Configuration> getConfigurations (){
              return Collections.unmodifiableList(this.configurations);
            }


          public void removeConfiguration(int index) //logic explicitly handle the remove
              { 
              this.configurations.remove(index);
            }

          }
他们仍然可以使用ReportGenerator的getter方法更改配置对象的状态,我认为这是不允许的。但是,如果我们想防止这种情况发生,我们必须在ReportGenerator类中声明更多的方法,以将调用转发到配置对象,并使用防御副本

所以我的问题是,如果您有一个对象a,其中包含另一个使用composition的对象B,并且它们都有getter和setter,那么您更喜欢通过a的getter方法更改对象B的状态吗? 例如

或者您更喜欢向A添加方法来更改B的状态(基本上是将呼叫转发给B)

例如

在该方法内部,调用B.setTitle(“”)


很抱歉问了这么长的问题,我想我不太确定我到底想问什么。希望你能理解P

编写代码时,最重要的是清晰性。你可以做你需要的事情,甚至改变实例的状态,但是如果可以的话,我不会这么做。除非你有一个很好的例子,即使用惰性初始化(第一次访问它时创建一个对象或值)

最后,这取决于具体情况,但我会尽量不改变getter上的对象状态

看起来其他人也这么想

。。

这可能适用于较小的类,但我会为您必须主控更复杂的对象层次结构而感到不寒而栗。想象一下,如果
A
突然有几个对象作为字段。你认为在每件衣服上都套上一个包装是个好主意吗?然后在每个对象变得更复杂时考虑这样做。有时做
A.getB().getC().setThingamabob()
比写
A.setSomething()
调用
B.setCField()
调用
C.setThingamabob()
更容易

如果您认为一个对象不应该是可变的,请删除setter。如果
a
的使用者根本不需要更改
B
,请不要提供
getB()
方法,而是提供类似于
a.setThingy()
的内容,其中未提及正在设置的内容是
B
的一部分


API契约并不一定意味着类必须为其所有属性提供getter/setter。如果消费者不打算直接读取/修改属性,请不要提供这样做的方法。

关于这是否是不良做法的答案是:“视情况而定”

一方面,返回对其内部状态的引用的类是一个“泄漏的抽象”。这是不好的,原因有很多:

  • 在API中显示类的实现细节会鼓励依赖于这些细节,这使得更改它们变得更加困难。(这在这里不是一个绝对的问题,但是如果您设计API,使修改getter返回的内容成为更改内容的标准方式,那么这可能很难处理……)

  • 如果细节显示为不可变的数据结构,客户端仍然可以看到“实时”更改,如果应用程序是多线程的,这可能是一个问题

  • 如果细节显示为可变的数据结构,客户机可以直接更改类的状态,绕过任何假设检查,等等,这是类通常执行的

  • 如果类在某些上下文中是“安全敏感”的,那么如果抽象存在漏洞,您就有各种额外的“向量”来破坏安全性

另一方面,使抽象不泄漏可能代价高昂:

  • 必须分配不可修改的集合包装器,并且它们添加了额外级别的方法调用

  • 返回副本会导致复制数据的额外开销。在多线程环境中,在创建副本时可能需要锁定源数据结构

最后,如果API需要允许客户端进行更改,那么通过泄漏的抽象进行更改实际上可能会为您提供更简单的API设计。泄漏问题可以通过(比如)使相关方法“包私有”来缓解

总之,这是“良好的OO设计”和实用性问题之间的权衡。你需要根据具体情况权衡这些因素


顺便说一下,你的问题标题和描述有误导性。比如说

  getConfigurations().remove(1); //remove a configuration via a getter
这是误导。您没有“通过getter”删除配置。您正在通过getter返回的对象删除它


(我只是吹毛求疵,但如果你想让人们理解你,你需要使用他们理解的语言。)

你在问从getter返回可变对象是否是个好主意。回答:有时候。你误解了这个问题。他问的是关于返回可变对象的问题。我确实理解……您可以返回可变VAT时间,但通常不会在getter中更改实例状态……这也是标题。感谢您提供的详细答案,我想这是逐案进行的,没有适合所有情况的完美设计。
  reportGenerator.getConfigurations().get(0).settTitle("test");
A.getB().setTitle("");
A.setBTitle("");
  getConfigurations().remove(1); //remove a configuration via a getter