Groovy @CompileStatic with bounded generics

295 Views Asked by At

The Groovy compiler doesn't seem to like this generic method.

@CompileStatic
class GroovyMain {
    enum Planet { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE }
    enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }

    static void main(String... args) {
        Planet p = getEnumValueFor('Venus', Planet.&valueOf, Planet.EARTH)
        Day d = getEnumValueFor('Sunday', Day.&valueOf, Day.MONDAY)

        println "$p $d"
    }

    static <T extends Enum<T>> T getEnumValueFor(String value, Closure<T> closure, T defaultValue) {
        try {
            return closure.call(value.toUpperCase())
        } catch (Exception ignore) {
            return defaultValue
        }
    }
}

I can "fix" this in at least three ways.

  • remove @CompileStatic
  • remove the generic bound extends Enum<T>
  • cast the result of the closure call

But these options reduce or eliminate type safety. Is there another way to satisfy the groovy compiler?

For reference, the equivalent Java code compiles without error.

class JavaMain {
    enum Planet { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE }
    enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }

    public static void main(String... args) {
        Planet p = getEnumValueFor("Venus", Planet::valueOf, Planet.EARTH);
        Day d = getEnumValueFor("Sunday", Day::valueOf, Day.MONDAY);

        System.out.print("" + p + ' ' + d);
    }

    static <T extends Enum<T>> T getEnumValueFor(String value, Function<String, T> closure, T defaultValue) {
        try {
            return closure.apply(value.toUpperCase());
        } catch (Exception ignore) {
            return defaultValue;
        }
    }
}
0

There are 0 best solutions below