Thoughts on Array Initialization in JavaONE 2025
Brian Goetz
brian.goetz at oracle.com
Sat Jul 26 21:48:49 UTC 2025
All of the points you raise that "arrays are not the abstraction you are
looking for" are absolutely true -- and well understood. The goal of
improving array creation is not to help arrays win market share away
from collections.
But there is a reason that the language has arrays, and that reason
hasn't gone away. Arrays are the bottom brick on which the tower of
better data structures are built. You can't have ArrayList or HashMap
without arrays. Arrays are part of the language for a reason. As we
improve the language, sometimes arrays have to improve with it. (For
example, if you have a non-implicitly-constructible value class NVA (one
who has no valid default value), and someone wants to create an array of
NVA![n], allowing the existing "zero the memory" array creation
expression to create it would undermine the integrity of the runtime by
exposing objects that are not in a valid state as determined by their
constructor. So we can't allow that, which means we have to provide
something else.)
If we hadn't found the need to improve other aspects of initialization,
we probably wouldn't have bothered to improve array initialization. But
because we are improving initialization more broadly, we have to do the
whole job. Not being able to create interesting arrays linguistically
would forever look like a weird omission.
Your suggestion -- "why not just" not improve array creation
linguistically, and shunt any sort of exotic array creation to a
privileged API -- leaves the user with little explanation for why the
tower stands up. The bottom brick is not there, instead replaced by
some sort of magic that seems to hold up the brick above it. While we
expect relatively few programmers to program with arrays (ideally, just
the guy who maintains ArrayList and HashMap, and the like), we should
provide linguistic mechanisms for properly using core linguistic
building blocks.
I can imagine three implicit lines of thought for why you think such a
low-level mechanism should be performed by a privileged library rather
than a language feature:
- The easier we make it to use, the more people will use it, and you
would like fewer people to use it (as would we.) A scary-looking
library will scare away more people than a pretty-looking language feature.
- Language features are expensive, more expensive than libraries, so
by shunting this to a library, we preserve resources to focus on more
important things.
- Array initialization appears to be competing for resources with
features like collection literals, and you'd rather have the latter, so
suggesting that we skip the former seems like it would bring the latter
more quickly.
These are appealing-sounding arguments, but they don't point to either
usability wins or project-management wins. Arrays are the right tool
for some jobs. Collections are the right tool for others (most
others.) But the way to encourage people to use the right tool is not
to make the other tools harder to use. (We too would like to have
linguistic support for creating sets, lists, maps, etc, but that feature
is not competing with arrays, its waiting for something else.) Nor is
the cost of a privileged array-construction API significantly cheaper
than a language feature.
Cheers,
-Brian
On 7/26/2025 5:03 PM, david Grajales wrote:
>
> Dear Amber developers,
>
> I recently watched the JavaONE 2025 session titled /“A New Model for
> Java Object Initialization”/ and was particularly intrigued by the
> proposed improvements to array initialization.
>
> https://www.youtube.com/watch?v=XtvR4kqK8lo
>
>
> I strongly agree that Java needs better mechanisms for initializing
> data structures in a concise, expressive, and stricter manner—similar
> in spirit to Python’s list comprehensions and aligned with Strict
> initialization, required for Valhalla. Such constructs can help avoid
> subtle bugs and the presence of unintended |null| values. However, I
> remain skeptical about the decision to focus this new model
> exclusively around arrays.
>
> As has been discussed over the past few months, arrays are not ideal
> as a default abstraction, especially for students or in enterprise
> applications. Arrays are a low-level construct with several limitations:
>
> *
>
> They do not integrate well with generics.
>
> *
>
> They are of fixed size.
>
> *
>
> They lack methods and flexibility.
>
> *
>
> They are syntactically and semantically inconsistent with the rest
> of the Java Collections Framework.
>
> In many ways, arrays are a legacy feature inherited from C/C++—much
> like the original |switch| statement—that carry forward certain
> limitations that Java has otherwise worked hard to overcome.
>
> Given these issues, Why not just create an small API that facilitates
> the creation of the most used data structures with strict initialization?
>
> For example:
>
>
> void main(){
>
>
> // toArray
>
> var array = StrictCollections.toArray(String.class, 5, i ->
> "Item-" + i);
>
> IO.println("Array: " + Arrays.toString(array));
>
>
> // toList
>
> var list = StrictCollections.toList(5, i -> "List-" + i);
>
> IO.println("List: " + list);
>
>
> // toSet
>
> var set = StrictCollections.toSet(5, i -> "Set-" + (i % 3));
>
> IO.println("Set: " + set);
>
>
>
> var map = StrictCollections.toMap(
>
> 5,
>
> i -> "Key-" + i,
>
> i -> i * 100
>
> );
>
> IO.println("Map: " + map);
>
>
> }
>
>
>
> public static class StrictCollections {
>
>
> public static <T> T[] toArray(Class<T> clazz, int size,
> IntFunction<T> function) {
>
> @SuppressWarnings("unchecked")
>
> T[] array = (T[]) Array.newInstance(clazz, size); // This
> could be a frozen array once these are ready
>
> for (int i = 0; i < size; i++) {
>
> array[i] = function.apply(i);
>
> }
>
> return array;
>
> }
>
>
> public static <T> ArrayList<T> toList(int size, IntFunction<T>
> function) {
>
> var list = new ArrayList<T>(size);
>
> for (int i = 0; i < size; i++) {
>
> list.add(function.apply(i));
>
> }
>
> return list;
>
> }
>
>
> public static <T> HashSet<T> toSet(int size, IntFunction<T>
> function) {
>
> List<T> list = new ArrayList<>(size);
>
> for (int i = 0; i < size; i++) {
>
> list.add(function.apply(i));
>
> }
>
> return new HashSet<>(list);
>
> }
>
>
> public static <K, V> HashMap<K, V> toMap(int size, IntFunction<K>
> kFunction, IntFunction<V> vFunction) {
>
> HashMap<K, V> map = new HashMap<>(size);
>
> for (int i = 0; i < size; i++) {
>
> map.put(kFunction.apply(i), vFunction.apply(i));
>
> }
>
> return map;
>
> }
>
> }
>
> While this is admittedly a rough sketch developed in just a few
> minutes, I believe a similar—much more thoroughly designed—approach
> could provide much greater flexibility with far less complexity than
> introducing a dedicated array-specific feature. It would also extend
> naturally to a broader range of use cases --Such as being able to be
> combined with the Stream API in a much more ergonomic way--.
> Furthermore, as value classes and parametric JVM start to make it into
> the language and the JVM, the advantages of arrays and primitive types
> will diminish further. In that context, arrays will become even less
> compelling in the future.
>
> If Java is to introduce a safe, expressive, and idiomatic strict
> initialization literal for data structures, I would argue it should
> primarily support |List|, |Set|, and |Map|—especially |Map|, which
> remains one of the least ergonomic structures to initialize in the
> language today, particularly when compared to alternatives in Dart,
> Python, or even JavaScript objects. Data structures that are much more
> used.
>
>
> Thank you so much for all your work and always yours
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20250726/ed49df7c/attachment-0001.htm>
More information about the amber-dev
mailing list