从内部匿名class访问外部匿名class的方法
Access method of outer anonymous class from inner anonymous class
我用实例化另一个匿名class的方法实例化一个匿名class,然后从这个内部匿名class我想调用一个属于外部匿名[=的方法42=]。为了说明这一点,假设我有这个界面:
interface ReturnsANumber {
int getIt();
}
然后,在我的代码中的某处,我这样做:
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
public int getIt() {
// In a modern version of Java, maybe I could do
// var a = this;
// and then call a.theNumber();
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return this.theNumber();
}
};
return w.getIt();
}
};
System.out.println("The number is " + v.getIt());
问题:
在最内层方法getIt
中,我想调用属于最外层匿名class的theNumber()
。如果不使用 Java 10 var 功能(如代码中提示的那样),我如何才能做到这一点。
澄清:理想情况下,外部匿名class不需要知道内部class想要调用它的theNumber
方法.这个想法是想出一些代码,让内部 class 明确调用外部 class.
上的 any 方法
换句话说,我怎样才能让这段代码显示:
The number is 119
(而不是显示 The number is 1
)
动机:
有人可能会问我为什么要这样做:我正在编写某种代码生成器,并想确保我生成的代码没有歧义。
没有用于访问封闭匿名的关键字 class。
但一种解决方案可能是在外部匿名 class 中代理该方法并进行不合格的引用:
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
//Just a different name for theNumber()
int theNumberProxy() {
return theNumber();
}
public int getIt() {
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return theNumberProxy(); //calls enclosing class's method
}
};
return w.getIt();
}
};
这种操作的需要足以证明您的 class 结构并不理想,可能成为维护陷阱。例如,您可以简单地将第一个匿名 class 替换为嵌套静态 class。
因为 Java 8 解决方案非常简单。只需将方法引用存储在变量中。
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
public int getIt() {
Supplier<Integer> supplier = this::theNumber;
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return supplier.get();
}
};
return w.getIt();
}
};
存储外部对象也可以解决问题。但 仅适用于继承方法:
interface ReturnsANumber {
int theNumber();
int getIt();
}
public int getIt() {
ReturnsANumber outer = this;
ReturnsANumber w = new ReturnsANumber() {
public int theNumber() {
return 1;
}
public int getIt() {
return outer.theNumber();
}
};
return w.getIt();
}
您也可以将方法引用或外部对象存储为字段。
更新
@Holger 提出了另一种解决方法。您可以将 outer 对象传递给 lambda:
ReturnsANumber v = new ReturnsANumber() {
...
@Override
public int getIt() {
ReturnsANumber w = Optional.of(this).map(outer ->
new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return outer.theNumber();
}
}).get();
return w.getIt();
}
};
如果可以扩展接口:
public class Test {
interface ReturnsANumber {
int theNumber();
int getIt();
}
public static void main(String[] args) {
ReturnsANumber v = new ReturnsANumber() {
public int theNumber() {
return 119;
}
public int getIt() {
final ReturnsANumber that = this;
// In a modern version of Java, maybe I could do
// var a = this;
// and then call a.theNumber();
ReturnsANumber w = new ReturnsANumber() {
public int theNumber() {
return 1;
}
public int getIt() {
return that.theNumber();
}
};
return w.getIt();
}
};
System.out.println("The number is " + v.getIt());
}
}
我用实例化另一个匿名class的方法实例化一个匿名class,然后从这个内部匿名class我想调用一个属于外部匿名[=的方法42=]。为了说明这一点,假设我有这个界面:
interface ReturnsANumber {
int getIt();
}
然后,在我的代码中的某处,我这样做:
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
public int getIt() {
// In a modern version of Java, maybe I could do
// var a = this;
// and then call a.theNumber();
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return this.theNumber();
}
};
return w.getIt();
}
};
System.out.println("The number is " + v.getIt());
问题:
在最内层方法getIt
中,我想调用属于最外层匿名class的theNumber()
。如果不使用 Java 10 var 功能(如代码中提示的那样),我如何才能做到这一点。
澄清:理想情况下,外部匿名class不需要知道内部class想要调用它的theNumber
方法.这个想法是想出一些代码,让内部 class 明确调用外部 class.
换句话说,我怎样才能让这段代码显示:
The number is 119
(而不是显示 The number is 1
)
动机: 有人可能会问我为什么要这样做:我正在编写某种代码生成器,并想确保我生成的代码没有歧义。
没有用于访问封闭匿名的关键字 class。
但一种解决方案可能是在外部匿名 class 中代理该方法并进行不合格的引用:
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
//Just a different name for theNumber()
int theNumberProxy() {
return theNumber();
}
public int getIt() {
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return theNumberProxy(); //calls enclosing class's method
}
};
return w.getIt();
}
};
这种操作的需要足以证明您的 class 结构并不理想,可能成为维护陷阱。例如,您可以简单地将第一个匿名 class 替换为嵌套静态 class。
因为 Java 8 解决方案非常简单。只需将方法引用存储在变量中。
ReturnsANumber v = new ReturnsANumber() {
int theNumber() {
return 119;
}
public int getIt() {
Supplier<Integer> supplier = this::theNumber;
ReturnsANumber w = new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return supplier.get();
}
};
return w.getIt();
}
};
存储外部对象也可以解决问题。但 仅适用于继承方法:
interface ReturnsANumber {
int theNumber();
int getIt();
}
public int getIt() {
ReturnsANumber outer = this;
ReturnsANumber w = new ReturnsANumber() {
public int theNumber() {
return 1;
}
public int getIt() {
return outer.theNumber();
}
};
return w.getIt();
}
您也可以将方法引用或外部对象存储为字段。
更新
@Holger 提出了另一种解决方法。您可以将 outer 对象传递给 lambda:
ReturnsANumber v = new ReturnsANumber() {
...
@Override
public int getIt() {
ReturnsANumber w = Optional.of(this).map(outer ->
new ReturnsANumber() {
int theNumber() {
return 1;
}
public int getIt() {
return outer.theNumber();
}
}).get();
return w.getIt();
}
};
如果可以扩展接口:
public class Test {
interface ReturnsANumber {
int theNumber();
int getIt();
}
public static void main(String[] args) {
ReturnsANumber v = new ReturnsANumber() {
public int theNumber() {
return 119;
}
public int getIt() {
final ReturnsANumber that = this;
// In a modern version of Java, maybe I could do
// var a = this;
// and then call a.theNumber();
ReturnsANumber w = new ReturnsANumber() {
public int theNumber() {
return 1;
}
public int getIt() {
return that.theNumber();
}
};
return w.getIt();
}
};
System.out.println("The number is " + v.getIt());
}
}