0

I'm new to Java and I'm using the current version of BlueJ to do my programming. When trying to initialize a string array containing all the days of the week I am greeted to the error message "generic array creation" I am curious on how to fix this as all the results I've found online have been quite old and out of date. The code is for a clock that can also track the day of the week. The code I have as follows:

daysOfWeek = new ArrayList<String>[]{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

I will be more than happy to update this post with any other information that may be needed to provide help. Thank you for your time.

Makk
  • 45
  • 6
  • I don't think you are allowed to pre-define values in an ArrayList. – FailingCoder Sep 23 '19 at 01:34
  • 1
    Use `List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday")`. It's just a List, not an ArrayList, – Johannes Kuhn Sep 23 '19 at 01:35
  • Possible duplicate of [Initialization of an ArrayList in one line](https://stackoverflow.com/questions/1005073/initialization-of-an-arraylist-in-one-line) – FailingCoder Sep 23 '19 at 01:37
  • 1
    `List daysOfWeek = new ArrayList<>(Arrays.asList("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"));` – Elliott Frisch Sep 23 '19 at 01:38
  • @JohannesKuhn I plan on having it tick through the array with the rest of the clock. Will that still work with a list? – Makk Sep 23 '19 at 01:39
  • @ElliottFrisch He uses Java 11, teach him the right thing to do: `List.of`. It's unlikely that the number of days in a week change anytime soon. – Johannes Kuhn Sep 23 '19 at 01:40
  • @Makk Yes. See https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface – Johannes Kuhn Sep 23 '19 at 01:41
  • 2
    @JohannesKuhn I'm still using Java 8, but I think the "right thing to do" would be: `List daysOfWeek = new ArrayList<>(Arrays.asList(java.time.DayOfWeek.values()));` (or `List.of(java.time.DayOfWeek.values())` since, as you say, Java 11+). [`DayOfWeek`](https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html) is a nice `enum`. Seems a shame to not use it. – Elliott Frisch Sep 23 '19 at 01:43
  • Using `java.time` is not a bad idea. There is always a better way to write some code. – Johannes Kuhn Sep 23 '19 at 01:45
  • @ElliottFrisch Because `DayOfWeek` is an `enum`, I'd personally opt for an `EnumSet` (`EnumSet.allOf(DayOfWeek.class);`), but that's a valid solution nonetheless. – Jacob G. Sep 23 '19 at 01:45
  • @JacobG. Then it would be easier: `EnumSet.allOf(DayOfWeek.class)`, but this is a `Set`, not a `List`. – Johannes Kuhn Sep 23 '19 at 01:47
  • 1
    Honestly, don't encourage people to use `Arrays.asList` except in super-specialist cases. A `List` that allows element mutation but not structural mutation? Eurgh. That sort of confusion we can all do without. `List.of` unless there is a very good reason not to. (Some of the streams API is worse.) – Tom Hawtin - tackline Sep 23 '19 at 02:05

1 Answers1

3

As of Java 13, generic array creation is still forbidden. The reason has to do with the fact arrays know their component type at runtime but generics suffer from what's known as type-erasure. That said, your question has the following example:

daysOfWeek = new ArrayList<String>[]{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

The above is trying to create an ArrayList<String>[]; in other words, an array of array-lists. This is most likely not what you actually want to do. Despite the name ArrayList, the class isn't directly involved in the creation of arrays—the name just means the list is backed by an array. Given that your data is simply the name of each day of the week, what you probably want is a String[] or List<String>:

// array
String[] daysOfWeek = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};

// list
List<String> daysOfWeek = new ArrayList<>(List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"));

Note that if you're not using Java 11+ you can replace the use List#of with Arrays#asList(T...). If you are using Java 11+ then consider using the result of List#of directly, rather than copying the result into a modifiable ArrayList (assuming you don't plan on modifying the list).

You may also want to consider using the java.time.DayOfWeek enum instead of a String to represent each day of the week. An enum is more type-safe, less prone to error, and allows easy interaction with any other java.time classes you may use.

List<DayOfWeek> daysOfWeek = List.of(DayOfWeek.values());

You should always default to using a List (or some other collection) before using an array. If you absolutely must use an array, you can work around the "generic array creation" error with the following:

// unbounded T
@SuppressWarnings("unchecked")
T[] array = (T[]) new Object[size];

// or if, for instance, T is upper-bounded by CharSequence
@SuppressWarnings("unchecked")
T[] array = (T[]) new CharSequence[size];

// or if the component type is itself generic
@SuppressWarnings("unchecked")
Comparator<String>[] array = (Comparator<String>[]) new Comparator[size];

However, all of the above is simply a compile-time trick. Each of the arrays will still allow any object that's an instance of the raw component type to be stored without throwing an ArrayStoreException at runtime. In other words, the first array will still accept any Object, the second array will still accept any CharSequence, and the third array will still accept any Comparator<?>. This is why an "unchecked cast" warning is emitted for each of the above; that is, if there were no @SuppressWarnings("unchecked") annotation present.

Slaw
  • 37,820
  • 8
  • 53
  • 80