CfD: compile-time checked immutable collections
Remi Forax
forax at univ-mlv.fr
Tue May 5 20:19:32 UTC 2020
Hallo !
This questions have been asked so many times since 1998,
Josh Bloch one of the designer of the API (who will later write Effective Java) as created a FAQ around that time answering to that question:
https://docs.oracle.com/javase/8/docs/technotes/guides/collections/designfaq.html
Google also tried to tackle the problem
https://github.com/google/guava/wiki/ImmutableCollectionsExplained
https://guava.dev/releases/21.0/api/docs/com/google/common/collect/ImmutableCollection.html
the section "Interfaces, not implementations" explains why you should not takes an immutable list as parameters
Some of those classes have been retrofitted in recent releases of the JDK (see List/Map/Set.of and List/Map/Set.copyOf)
Some IDEs can emit a warning or an error if you try calls a method that can throw UnsupportedOperationException on a map/collection you receive as return value of a call,
usually it's enough to detect 99% of the bugs.
regards,
Rémi
----- Mail original -----
> De: "M. Kroll" <michaelkroll at mail.de>
> À: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Envoyé: Mardi 5 Mai 2020 20:55:00
> Objet: CfD: compile-time checked immutable collections
> Hey there!
>
> I am new here so first i want to introduce myself. My name is Michael
> and i live in germany. For a job i am a java developer with 10 years of
> java EE experience. At work my passion is to create long-living core
> tools for our projects.
>
> But now for the reason i joined openjdk and this group in particular:
> immutable collections.
>
> During development i sometimes stumble upon the fact that there is no
> simple way build an immutable object that exposes a read-only
> collection, and all this in a compile-time safe manner. To explain it
> with code, i want to have something like this:
>
> class Example {
> private final Collection<String> values;
> public Example(String... args) { this.values = Arrays.asList(args); }
> public Collection<String> getValues() { return values; }
> }
> class Test {
> public void test() {
> Collection<String> v = new Example("a","b","c").getValues();
> v.clear(); // <-- compile time error
> }
> }
>
> The current approach to this is using either
> Collections.unmodifiableXYZ(...), which may lead to runtime exceptions.
> Or we use Stream as return object, but there is no simple way to pass
> that around and use it multiple times. I don't see Supplier<Stream> as a
> solution to this: determining the size of the collection would need to
> traverse the whole stream, even if the underlying collection is an
> arraylist... not good.
>
> My approach to this would be to split up the Collection-Interface into a
> read-only and a mutating part.
>
> But before i present you my somewhat complete solution, i asked myself
> if you already discussed something like that. So i dived into the bug
> database and found 3 somewhat similar tickets:
>
> 1. https://bugs.openjdk.java.net/browse/JDK-6432147
> The author wanted to introduce annotations to mark objects as
> immutable and on basis of this raise compile exceptions. This would need
> a load of annotations throughout the code and additional rules to check
> by the compiler. The ticket was closed as a duplicate to [2]
> 2. https://bugs.openjdk.java.net/browse/JDK-4211070
> The author wanted to introduce a new keyword 'const' to be used
> just like the annotation in [1]. Same problem: massive spray of the new
> keyword throughout the code and the need for a change in the compiler
> and even in the language.
> 3. https://bugs.openjdk.java.net/browse/JDK-5099784
> This is as old as JDK1.4.2 (2004) and proposes the same way i want
> to go: split the Collection-interface into a new parent-interface that
> contains all non-modifying methods and the Collection-interface itself
> that then only contains modifying methods. A user of the
> Collection-interface would see the same API as before, a user of the new
> parent-interface would only see read-only methods.
>
> The original author of [3] is inactive by now, the ticket itself was not
> discussed and is still unresolved open.
>
> I would happily try to implement this approach, but first i want to know
> if this is the way to go and what your thoughts are about this.
>
> Hope this is not too much text for a Call for Discussion,
> Michael
More information about the core-libs-dev
mailing list