Skip to content
Advertisement

Why enum constructor “this” and “Enum.this” is different

I have a local enum cache, need in enum constructor return enum instance. but when return ‘this’ , it’s fail, return ‘Enum.this’ , it’s ok. the exception looks like a inner class. because this instance is not finish ? this is my code and exception

public static void main(String[] args) {
        TestEnum testEnum = EnumManager.byK1(TestEnum.class,0);
}
public final class EnumManager {

    private static final Map<Class,Map<String,Object>> K1_MAP = new HashMap<>(16);

    private static final Map<Class,Map<String,Object>> K2_MAP = new HashMap<>(8);

    private static final Map<Class,Map<String,Object>> K3_MAP = new HashMap<>(4);



    public static void register(Class clazz, EnumGetter getter){
        Map<String,Object> k1 = K1_MAP.computeIfAbsent(clazz,k -> new HashMap<>(4));
        Map<String,Object> k2 = K2_MAP.computeIfAbsent(clazz,k -> new HashMap<>(4));
        Map<String,Object> k3 = K3_MAP.computeIfAbsent(clazz,k -> new HashMap<>(4));
        if (Objects.nonNull(getter.getK1())){
            k1.put(getter.getK1().toString(),getter.get());
        }
        if (Objects.nonNull(getter.getK2())){
            k2.put(getter.getK2().toString(),getter.get());
        }
        if (Objects.nonNull(getter.getK3())){
            k3.put(getter.getK3().toString(),getter.get());
        }
    }

    public static <T> T byK1(Class clazz, Object k){
        return by(K1_MAP,clazz,k.toString(),null);
    }

    public static <T> T byK1(Class clazz, Object k, T def){
        return by(K1_MAP,clazz,k.toString(),def);
    }

    public static <T> T byK2(Class clazz, Object k){
        return by(K2_MAP,clazz,k.toString(),null);
    }

    public static <T> T byK2(Class clazz, Object k,T def){
        return by(K2_MAP,clazz,k.toString(),def);
    }

    public static <T> T byK3(Class clazz, Object k){
        return by(K3_MAP,clazz,k.toString(),null);
    }

    public static <T> T byK3(Class clazz, Object k, T def){
        return by(K3_MAP,clazz,k.toString(),def);
    }


    private static <T> T by(Map<Class,Map<String,Object>> map, Class clazz ,String key, T def){
        Map<String,Object> m1 = map.get(clazz);
        if (m1 == null){
            clazz.getEnumConstants();
            m1 = map.get(clazz);
        }
        if (m1 != null){
            try {
                return (T) m1.getOrDefault(key,def);
            } catch (Exception e) {
                log.error("conversion type error",e);
            }
        }
        return def;
    }


}
public enum TestEnum {
    A_1(0, "A1");

    private int code;
    private String description;

    private TestEnum(int code, String description) {
        this.code = code;
        this.description = description;
        System.out.println(this.getClass());
        System.out.println(this.getClass());
        EnumManager.register(TestEnum.class, new EnumGetter() {
            public Object get() {
                return this;
            }

            public Object getK1() {
                return code;
            }

            public Object getK2() {
                return null;
            }

            public Object getK3() {
                return null;
            }
        });
    }

    public int getCode() {
        return this.code;
    }

    public String getDescription() {
        return this.description;
    }
}

enter image description here

enter image description here

Advertisement

Answer

Here:

EnumManager.register(TestEnum.class, new EnumGetter() {
  public Object get() {
    return this;
  }

  public Object getK1() {
    return code;
  }

  public Object getK2() {
    return null;
  }

  public Object getK3() {
    return null;
  }
});

Notice that the get method is inside of an anonymous inner class new EnumGetter() { ... }. This creates a class like this.

// assuming EnumGetter is an interface
// this class doesn't actually have this name. As you can see from the error message,
// its name actually is "TestEnum$1"
class SomeAnonymousClassName implements EnumGetter {
  public Object get() {
    return this;
  }

  public Object getK1() {
    return code;
  }

  public Object getK2() {
    return null;
  }

  public Object getK3() {
    return null;
  }
}

Imagine this code being placed inside of TestEnum. So inside of get, the unqualified word this refers to the current instance of SomeAnonymousClassName, rather than the instance of the enum.

As the Java Language Specification says:

When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method or default method was invoked, or to the object being constructed.

To refer to the current instance of the enum, you have to use TestEnum.this.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement