Returning const reference of an arraylist

谁说胖子不能爱 提交于 2019-12-21 07:08:39

问题


I really admire java features and I don't want to give up using it for the next problem:

I have a class that might be inherited, and inside of it is a private ArrayList arr; So the setter function is ok , but the getter function return arr; returns the reference to that variable which anyone capable of editing that whole array which I don't want and private wouldn't make any sense !

In C++ I would just return const arr; and it would return constant reference to the variable.

I so much need the variable not to be cloned or manually copied because there are so many calculations that require to (READ ONLY the variable) WHY there is no const returning in java ???? is there any way I could escape copying ?

p.s (final ArrayList<Integer> arr;) isn't an option cause that array always changes size or element values.

If I couldn't find a fix to that I'm threatening to go back to C++ or make everything public and you should never get my software :D


EDIT: one more important question: Am I asking for something that's not good (Software engineering wise) I mean if JAVA creators thought of not having const reference (returning Read only references) then I must be asking for something that can be handled in other way. or my program design is wrong I'm so confused.


回答1:


Wrap the return value with java.util.Collections.unmodifiableList. It does not make a copy of the data, but wraps the original list, and delegates read-only operations to the underlying list. Operations which would modify the list are rejected at runtime via UnsupportedOperationException.

Your

return arrayList;

becomes

return Collections.unmodifiableList(arrayList);

Unfortunately the read-only constraints won't be enforced by the compiler. They will, however, be enforced at runtime.

You also have available to you: unmodifiableSet, unmodifiableMap, unmodifiableCollection, unmodifiableSortedSet, and unmodifiableSortedMap. And if these are not enough, you can still take inspiration from this general design approach, and create your own custom read-only wrapper classes.




回答2:


:) You have several options:

  • Don't expose getter, provide only methods which are allowed to call, e.g.

    public void addToList(Object arg) { this.arr.add(arg);}

  • Return immutable object:

    public List getArr() { return Collections.unmodifiableList(this.arr); }




回答3:


You could also use Google Guava's immutable collections. In this case, you would store an ImmutableList in your field.

Of course, if your class needs to modify this list internally, using ImmutableList might turn out to be a bad idea, since you'll need to create a new ImmutableList instance and reassign it to the field each time...

But it's perfect when you know the List won't change after object construction.

Immutable example (list won't change after object construction)

@Immutable
public final class Foo {

    @Nonnull
    private final ImmutableList<String> list;

    public Foo(@Nonnull List<String> list) {
        // you could also compute the appropriate list here
        // before assigning it to the field
        this.list = ImmutableList.copyOf(list);
    }


    public ImmutableList<String> getList() {
        return list;
    }
}

Mutable example (list may only be modified using the setter)

public class Foo {

    @Nonnull
    private ImmutableList<String> list = ImmutableList.of();

    public ImmutableList<String> getList() {
        return list;
    }

    public void setList(@Nonnull List<String> list) {
        this.list = ImmutableList.copyOf(list);
    }
}

Remarks

  • I know it's often advised to make methods return the most generic type possible (List in this case), but I prefer to declare my getter's return type as an ImmutableList, because it acts as documentation (no need to document the returned list's immutability in the Javadoc) and as an API contract. It's like saying "I guarantee this list to be immutable, you do not have to worry or defensively copy it". And it is very concise.
  • ImmutableList.copyOf() is great, since it automatically rejects null lists (by throwing NullPointerException). It also rejects null elements. And it won't copy the source list if it's already an ImmutableList, which avoids useless object instantiation.
  • In the second example, I initialize the field to an empty ImmutableList using ImmutableList.of(), because it's a good practice to return empty collections instead of null values (Null Object pattern). You might think that this creates needless object instantiation, but ImmutableList.of() actually returns a singleton.



回答4:


There is an alternative to the unmodifiableList method. You can just return a copy of this private array. For example,

    return your_private_array.clone();

Well, there could be a performance penalty for this. But you have interface unchanged (you still return an array).




回答5:


unmodifiableList is definitely the answer.



来源:https://stackoverflow.com/questions/4262434/returning-const-reference-of-an-arraylist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!