1

What I am trying to build is a list of enum classes that have got more advanced valueOf methods. Since that method cannot be overwritten and therefore extended, I have thought to make a class holding all enumerations which have advancedValueOf methods and run it by lambda. The problem I am facing is that registration of the enum is in static{} code, which is triggered AFTER the enum is checked for the first time.

public enum SimpleEnum
{
    ONE,
    TWO;
    static
    {
        EnumTest.registerEnum(SimpleEnum.class, SimpleEnum::advancedValueOf);
    }
    public static SimpleEnum advancedValueOf(String s)
    {
        return ONE;//This method would find enum by its parameters
    }
}

//------------------------------------------------

public class EnumTest
{
    private static final Map<Class<?>, Function<String, ?>> _advancedValueOfEnums = new HashMap<>();

    public static void main(String[] args)
    {
        getValue(SimpleEnum.class, "1");
    }

    public static <T extends Enum<T>> void registerEnum(Class<T> enumClass, Function<String, T> advancedValueOf)
    {
        _advancedValueOfEnums.put(enumClass, advancedValueOf);
    }

    public static void getValue(Class<?> enumClass, String value)
    {
        System.out.println("Contains=" + _advancedValueOfEnums.containsKey(enumClass));
    }
}

Message printed to the console is "Contains=false". What can I do to make it "Contains=true"?

This answer: Why can't enum's constructor access static fields? shows what is wrong with accessing static field from enum constructor, I am asking about accessing static value of enum from a different class which should have already been initialized.

  • 1
    @nullpointer beyond the hack, having this kind of requirement generally means you did some mistakes in your design. I would like to answer about this point. – davidxxx Sep 08 '18 at 14:37
  • I am trying to make values like "DUAL_SWORD" & "Dual Sword" & "Dual" be acceptable by xmls, but enum class is known only at runtime so I can see only above solution or calling "advancedValueOf" via reflection –  Sep 08 '18 at 14:44
  • @davidxxx Can we add it to the original post in such cases? I am not sure what's the consensus over such approach on SO, but please feel free to reopen if it should be done here. – Naman Sep 08 '18 at 15:01
  • @nullpointer I don't know really but as the dup doesn't suit completely to the actual question and that I have you agreement, I reopen. Thanks ! – davidxxx Sep 08 '18 at 19:53
  • 1
    Why do the enum classes need to register themselves with class `EnumTest`? I suggest decoupling the enums from class `EnumTest`, and instead performing the wanted registrations separately, perhaps as directed by a configuration file. – John Bollinger Sep 08 '18 at 20:00

1 Answers1

0

You could make the enum class be loaded before by performing any invocation on the enum such Enum.values() :

public static void main(String[] args){
    SimpleEnum.values();  // hack to load the enumeration class
    getValue(SimpleEnum.class, "1");
}

But that is a hack : not readable and easily broken by a change as these are two distinct classes.
I think that the separation between EnumTest and SimpleEnum is too artificial and their effective coupling too high : SimpleEnum depends on EnumTest that itself depends on SimpleEnum.
Either use a single class : just the enum class or keep your two classes but by making a real distinction between their responsibilities.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • In my example, I have set EnumTest to be responsible for checking value and also for holding enums, but it was made here only to shorten code as much as I can. It is also not possible to place everything in one enum because I have got couple of enums with "advancedValueOf" method. –  Sep 10 '18 at 11:07