1

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;
        }
    }
}
jaco0646
  • 15,303
  • 7
  • 59
  • 83
  • When you say "_doesn't seem to like_", can you say exactly what the computer outputs? – tim_yates Jun 14 '19 at 20:28
  • `Groovyc: [Static type checking] - Cannot return value of type java.lang.Object on method returning type T` – jaco0646 Jun 14 '19 at 20:29
  • 1
    My guess would be that it's the closure... Does it work with a function as with the Java example you show? What version of groovy? – tim_yates Jun 14 '19 at 21:01
  • 1
    Great question. It does work with a `Function` if the `.&` syntax is replaced by a closure: `{ Planet.valueOf(it) }`. I think that's a viable answer. This is groovy 2.5.6. Thanks. – jaco0646 Jun 14 '19 at 23:07
  • Does it work with the closure, if you replace the `.&` with `{ Planet.valueOf(it) }` – tim_yates Jun 15 '19 at 08:40
  • No, that produces the same error. – jaco0646 Jun 17 '19 at 13:39

0 Answers0