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
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... 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/Immutable... 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@mail.de> À: "core-libs-dev" <core-libs-dev@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
Thank you for your reply. I am not truly satisfied with this explanation (especially Josh Blochs "i am unwilling to create a few more interfaces" - sounds a bit silly if you look at all those unmodifiable-workarounds that are in place by now, even those incorporated into IDEs to warn the developer), but i'll get to that later. Nevertheless, could you please close the tickets i mentioned, commenting with the same text you sent me? I think that in the future people would benefit from finding an explanation before diving deeper into this topic on their own... or asking basic questions here. regards, Michael Am 05-May-2020 23:56:43 +0200 schrieb forax@univ-mlv.fr: 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... 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/Immutable... 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, Rmi ----- Mail original -----
De: "M. Kroll" : "core-libs-dev" 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 values; public Example(String... args) { this.values = Arrays.asList(args); } public Collection getValues() { return values; } } class Test { public void test() { Collection v = new Example("a","b","c").getValues(); v.clear(); // } }
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 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
participants (3)
-
M. Kroll
-
Michael Kroll
-
Remi Forax