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; } }
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
.