在java中使用getter方法向List添加元素是不好的做法?

假设我在类中有一个private ArrayListLinkedList ,我永远不会为它分配新的引用,换句话说,这将永远不会发生:

 myLinkedList = anotherLinkedList; 

这样我就不需要使用setMyLinkedList(anotherLinkedList)

但! 我需要添加元素,或从中删除元素。

  • 我应该只编写一种新的setter ,执行adding而不是setting的任务,比如myLinkedList.add(someElement)

  • 或者可以通过使用getter来执行此操作,而不必违反Encapsulation主体?

    getMyLinkedList().add(someElement)

(+假设如果我不服从封装,我将失去我的标记: – “)

我不认为做一些特别好的做法:

 myObj.getMyList().add(x); 

因为你是以非只读方式公开私有类变量,但据说我经常看到它(我正在看你,自动生成的类)。 我认为不是这样做,而是返回一个不可修改的列表,并允许该类的用户通过显式方法添加到列表中:

 public class MyClass{ private final List myList = new ArrayList(); public List getList(){ return Collections.unmodifiableList(this.myList); } public void addToList(final String s){ this.myList.add(s); } } 

编辑在审核了您的评论之后,我想补充一下您的setter想法:

我的意思是在类本身内部的一种新的setter中使用那行代码,比如public void setter(someElement){this.myLinkedList.add(someElement);}

如果我正确理解你,你说你想要公开一个只添加到你的列表中的方法。 总的来说,这就是我认为你应该拍摄的内容,以及许多人在答案中概述的内容,然而,将其标记为制定者有点误导,因为你没有重新分配(设置)任何东西。 那,我强烈建议如果可能的话,从你的getter方法中返回一个只读列表。

通常,您不应该假设getter返回的列表是原始列表。 例如,它可以被装饰或代理。 如果要防止在目标对象上设置新列表,则可以在目标类上定义add方法。

我建议在这种情况下,最好遵循您的Encapsulation主体并使用一种方法向列表中添加元素。 您通过将其设置为private来限制对列表的访问,以便其他类无法直接访问数据类型。

让存储ArrayList的类可以直接访问列表,但是当其他类想要添加到列表时,请使用add()方法。

只要你有一个任何类型的Collection ,如果有意义的客户端可以添加或删除私人列表中的对象,那么add()remove()等方法add()到类的接口通常并不是一个坏主意。 。

为什么实现这些额外的方法是有用的(它可能看起来像是矫枉过正,因为所有这些方法大多只是在Collection上调用方法)是你保护邪恶的客户端做你不想要的事情他们这样做,因为大多数Collection的界面不仅包含add()remove()方法,而且大多数情况下,你不希望客户搞乱你无法控制的事情。 因此,封装原则对您的老师很重要。

另一个优点:如果在任何时候,当您将一个对象添加到列表中时,您将决定必须满足某个条件,这可以通过您已有的方法轻松实现。 如果您让客户端访问列表的直接引用,那么实现这种事情并不容易(这种情况并不罕见)。

希望这可以帮助

这取决于应用 – 两者都是可以接受的。 仔细查看您正在编写的课程,并决定是否允许用户直接访问列表的内容,或者您​​是否希望首先通过某个中间过程。

例如,假设您有一个类ListEncrypter ,它包含您的MyLinkedList列表。 此类的目的是加密存储在MyLinkedList任何MyLinkedList 。 在这种情况下,您需要提供自定义添加方法,以便在将添加的项放入列表之前处理添加的项,如果要访问该元素,还需要处理它:

 public void add(Object element) { MyLinkedList.add(encrypt(element);); } public Object get(int index) { return decrypt(MyLinkedList.get(index);); } 

在这种情况下,您显然想要拒绝用户访问MyLinkedList变量,因为内容将被加密,并且它们将无法对其执行任何操作。

另一方面,如果您没有真正对数据进行任何处理( 并且您确定将来不再需要 ),则可以跳过创建专用方法并允许用户直接访问通过get方法列表。

如果我正确理解你的问题,你有一个包含List的类(它应该是final ,但你没有提到),并且你想允许调用者添加到List ,但是不能替换它。

你可以为列表提供一个getter:

 public List getMyList() { return myList; } 

或者提供添加到该列表的方法:

 public void addToMyList(E e) { myList.add(e); } 

两者都是有效的设计决策,但您使用的将取决于您的用例。 第一个选项使呼叫者可以直接访问List ,从而有效地将其公开。 当用户重复修改和使用列表时,这很有用,但可能会有问题,因为您无法再信任List处于任何可靠的状态(调用者可以清空它,或重新排序它,甚至恶意插入对象不同类型的)。 因此,只有在您打算信任调用者时才应使用第一个选项。

第二个选项为调用者提供了更少的function,因为他们一次只能添加一个元素。 如果要提供其他function(插入,添加等),您必须依次包装每个操作。 但它会让您更有信心,因为您可以确定List仅以您赞同的方式进行修改。 后一个选项也隐藏(封装)您正在使用List的实现细节,因此如果封装对您的用例很重要,您希望采用这种方式避免暴露内部数据结构,并仅暴露行为你想授予来电者。