方案一:对象注册系统
所展示的两个 sn-ps 本质上是在存储对刚刚创建的匿名类实例的引用或立即访问其自定义字段之间做出选择。做一个似乎会失去做另一个的能力。
达成妥协的一种方法是拥有一个对象注册系统,并在您的匿名类中使用实例初始化程序 (JLS 8.6) 自行注册到此系统。
这是一个简单的概念验证,使用Object[] 进行简单的注册系统:
final Object[] registrar = { null };
int k = new HashSet<Integer>(){
{ registrar[0] = this; }
int i= 666;
}.i;
Set<Integer> set = (Set<Integer>) registrar[0];
System.out.println(k); // 666
System.out.println(set.getClass().isAnonymousClass()); // true
本质上,我们使用 1 元素 Object[],并且在匿名类的实例初始化程序中,我们将 this“注册”到此数组。请注意,这只是一个概念验证;在生产代码中,您将使用比这更健壮和类型安全的对象注册系统。
解决方案 2:元组
如果您的匿名类可能有多个“字段”,则此方法非常有效。只需将它们全部打包到 tuple 中,确保在匿名类中包含对 this 的引用。
这是一个简单的概念验证,使用 Object[] 作为元组:
Object[] tuple = new HashSet<Integer>(){
Object[] tuple = { this, 666, 13, "XXX", "OMG ABUZE" };
}.tuple;
Set<Integer> set = (Set<Integer>) tuple[0];
set.add(null);
System.out.println(set.getClass().isAnonymousClass()); // true
System.out.println(Arrays.toString(tuple));
// [[null], 666, 13, XXX, OMG ABUZE]
在生产代码中,您将使用更面向对象和类型安全的CustomTuple 类。请注意,这是“我的方法如何返回 2 个值”问题的类似解决方案:只需返回 1 个值即可捕获所有这些信息。