Is it a bad practice to add elements to List using getter method in java?

前端 未结 6 2061
北海茫月
北海茫月 2020-12-15 20:44

Suppose I have a private ArrayList or a LinkedList inside a class, that I will never assign new reference to it, or in other words this will never

相关标签:
6条回答
  • 2020-12-15 21:00

    So you have a class containing a List field (it should be final, since you don't intend to assign to it), and you want to allow callers to add to the List, but not be able to replace it.

    You could either provide a getter for the list:

    public List<E> getMyList() {
      return myList;
    }
    

    Or provide a method to add to that list:

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

    Both are valid design decisions, but which you use will depend on your use case. The first option gives callers direct access to the List, effectively making it public. This is useful when users will be modifying and working with the list repeatedly, but can be problematic as you can no longer trust the List is in any sort of reliable state (the caller could empty it, or reorder it, or even maliciously insert objects of a different type). So the first option should only be used when you intend to trust the caller.

    The second option gives the caller less power, because they can only add one element at a time. If you want to provide additional features (insertion, add-all, etc.) you'll have to wrap each operation in turn. But it gives you more confidence, since you can be certain the List is only being modified in ways you approve of. This latter option also hides (encapsulates) the implementation detail that you're using a List at all, so if encapsulation is important for your use case, you want to go this way to avoid exposing your internal data structures, and only expose the behavior you want to grant to callers.

    0 讨论(0)
  • 2020-12-15 21:07

    I don't think it a particularly great practice to do something like:

    myObj.getMyList().add(x);
    

    since you are exposing a private class variable in a non read only way, but that being said I do see it pretty frequently(I'm looking at you, auto generated classes). I would argue that instead of doing it that way, return an unmodifiable list and allow users of the class to add to the list via an explicit method:

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

    EDIT After reviewing your comments, I wanted to add a bit about your setter idea:

    I meant using that line of code inside a new kind of setter inside the class itself, like public void setter(someElement){this.myLinkedList.add(someElement);}

    If I'm understanding you correctly, you are saying you want to expose a method that only adds to your list. Overall this is what I think you should be shooting for, and what many have outlined in the answers, however, labeling it as a setter is a bit misleading since you are not reassigning (setting) anything. That, and I strongly recommend returning a read only list from your getter method if possible.

    0 讨论(0)
  • 2020-12-15 21:07

    I would suggest in this case it would be best to follow your Encapsulation principals and use a method for adding elements to the list. You have restricted access to your list by making it private so that other classes cannot directly access the datatype.

    Let the class that stores your ArrayList have direct access to the list, but when other classes want to add to the list, use an add() method.

    0 讨论(0)
  • 2020-12-15 21:10

    As soon as you have a Collection of any kind, it is generally not a bad idea to add methods like add(), remove() to the interface of your class if it makes sense that clients can add or remove objects from your private list.

    The reason why it is useful to have these extra methods implemented (it might seem like overkill, because after all those methods mostly just call the method on the Collection) is that you protect evil clients from doing things to your list you don't want them to do, because the interface of most Collections contain more than just the add() and remove() methods and mostly, you don't want clients to be messing around with things you can't control. Therefore the encapsulation principle is that important to your teacher.

    Another plus: if at any time, you would decide that a certain condition must be met when an object is added to your list, this can easily be implemented in the method you already have. If you give a client access to the direct reference of your list, it is not easy at all to implement this kind of things (which are not rare).

    Hope this helps

    0 讨论(0)
  • 2020-12-15 21:15

    It depends on the application - both are acceptable. Take a good look at the class you're writing and decide if you want to allow users to directly access the contents of the list, or if you would prefer that they go through some intermediate process first.

    For example, say you have a class ListEncrypter which holds your MyLinkedList list. The purpose of this class is to encrypt anything that is stored in MyLinkedList. In this case, you'd want to provide a custom add method in order to process the added item before placing it in the list, and if you want to access the element, you'd also process it:

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

    In this case, you clearly want to deny the user's access to the MyLinkedList variable, since the contents will be encrypted and they won't be able to do anything with it.

    On the other hand, if you're not really doing any processing of the data (and you're sure you won't ever need to in the future), you can skip creating the specialized methods and just allow the user to directly access the list via the get method.

    0 讨论(0)
  • 2020-12-15 21:23

    In general, you should not assume that the list being returned by the getter is the original one. It could be decorated or proxied for example. If you want to prevent that a new list is set on the target object, you could define an add method on the target class instead.

    0 讨论(0)
提交回复
热议问题