4

In Java you could return a list that cannot be modified by the caller by doing return Collections.unmodifiableList(list).

Should the method name indicate that it's returning an unmodifiable list? That could prevent clients of my class from attempting to add or remove objects from the list.

3
  • 2
    I'm not that into java at the moment so maybe this is stupid, but in C# I would just make the method return an IEnumerable<T> instead of an IList<T>. Why not return an Iterable if you don't want to allow mutation?
    – sara
    Apr 15, 2016 at 12:12
  • @kai - I would certainly advocate such an approach if you simply want a client to iterate across it (see my answer below) Apr 15, 2016 at 14:50
  • 1
    Iterable is modifyable
    – Basilevs
    Apr 16, 2016 at 9:08

4 Answers 4

4

Not knowing that the method simply returns a List, my first reaction was this:

No, the method name should reflect what the method does in terms of the problem domain. Nowadays, I can see no reason for adding type information to method (or object) names. The return type should be easily displayed by any decent IDE.

This might have been different way back when people mostly read code in a simple text editor or printed out on paper. In these times, naming conventions like Hungarian Notation actually made sense.

This also applies to the name of the returned object in the calling function.

Now, having learned what Collections.unmodifiableList(list) actually does, I have to say, yes, make it really obvious in the method name and in the object name.

But most of all, I would try to avoid using this method at all. I would consider it very dangerous that the check is only performed at runtime.

2
  • 1
    The IDE will just show that the return value is a list, there's no way for it to show that the list is unmodifiable (since "unmodifiable list" isn't a data type).
    – TMN
    Apr 15, 2016 at 11:00
  • 2
    @FrankPuffer - unfortunately, Java doesn't provide the option of performing the check at compile time, runtime is the only option. Using the method is a better option than not, because failing quickly at runtime with an exception is better than obscure bugs occurring later because a collection that shouldn't have been modified has been.
    – Jules
    Apr 21, 2016 at 8:17
4

The unmodifiableList() method should have returned a new type that makes it obvious that it's unmodifiable. See this question for a discussion about why this wasn't done.

As it is, you must make this limitation clear yourself. Usually it should be enough to mention this in the method's API documentation, particularly if it's obvious from the domain that inserting or deleting can't possibly work (nobody expects to be able to found a new country in the world just because findCountries() technically returns an Object with an add() method).

If your domain is not so clear-cut, it can be a good idea to make the limitation even clearer via the method name. For instance, if you have a supportedFlavors() method, it would not be totally unreasonable to believe that you can change the supported flavors by manipulating the list, and adding a warning via the name could be a better idea.

2
  • The unmodifiableList() returns a List, so I'm not sure what you mean - you said it should return a new type that makes it obvious that's it unmodifiable. docs.oracle.com/javase/7/docs/api/java/util/… Apr 15, 2016 at 10:50
  • What he seems to mean is that unmodifiableList() should have returned a type for which the compiler ensured it is unmodifiable (by the type not having an add() method f.e.). This is not the case for the returned list as is, but is for instance the case for c#'s IEnumerable. I agree and the link elaborates, +1'd.
    – Hirle
    Apr 21, 2016 at 7:56
2

Sometimes I document this by returning Collection<? extends ElementType> instead of Collection<ElementType>. That way adding elements is clearly unsupported. And remove being unsupported is thus implied. You might make it more explicit if

  • it is a public API
  • source is not readily available to clients of the interface
  • the domain is not obvious
3
  • +1 - this is a nice answer. A bit of a hack, but it will make the compiler catch errors, rather than leaving them until runtime.
    – Jules
    Apr 21, 2016 at 8:20
  • You can still add null- ok, probably not by accident. And the compiler won't provide any errors or warnings on calling clear etc.
    – Hulk
    May 17, 2016 at 14:03
  • @Hulk: If you really want to, you can still mess up. I only add it as a hint / documentation. If there is an explicit need to avoid changes to the result, you should use one of the Collections.unmodifiableXXX methods.
    – Jaap
    May 17, 2016 at 14:09
2

You wrote:

Should the method name indicate that it's returning an unmodifiable list? That could prevent clients of my class from attempting to add or remove objects from the list.

No. Your interface needs to enforce the read-only nature (and, as an aside, you need to decide if the object returned is immutable, or whether it can change whilst your clients are inspecting or holding it. i.e. is defensive copying a valid goal here?).

8
  • 1
    I think it can't be stressed enough. don't focus on how to punish developers for doing something wrong (by throwing exceptions and making them read obscure docs). focus on making the right thing the only thing you're physically able to do!
    – sara
    Apr 15, 2016 at 15:00
  • I like the idea of returning an Iterator, but often the user also needs to check the size of the Collection. Wish there were an IteratorAndSize interface. :-)
    – user949300
    Apr 15, 2016 at 16:43
  • 3
    Iterator.remove()
    – Basilevs
    Apr 16, 2016 at 9:11
  • 1
    I return a list that is unmodifiable by using Collections.unmdofiableList, is there anything wrong about it? Clients cant modify it, and even if they try to, an exception will be thrown. So my interface DOES enforce that the returned list is unmodifiable. Im asking if the method name should indicate it as well. Apr 16, 2016 at 9:55
  • The runtime enforces this but the compiler doesn't. So someone can write code that will throw an exception when running. You really want the compiler to reject the code out of hand instead Apr 16, 2016 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.