是否有任何Java语法可以从外部类访问匿名内部类中定义的新方法?我知道可以有多种解决方法,但我想知道是否存在特殊的语法?
例如
class Outer {
ActionListener listener = new ActionListener() {
@Override
void actionPerformed(ActionEvent e) {
// do something
}
// method is public so can be accessible
public void MyGloriousMethod() {
// viva!
}
};
public void Caller() {
listener.MyGloriousMethod(); // does not work!
}
}
我自己的解决方案
我只是将所有方法和成员移到了外部类。
一旦匿名类实例被隐式转换为命名类型,就无法将其强制转换回来,因为匿名类型没有名称。您可以通过类中的this
访问匿名内部类的其他成员,在表达式之后紧跟在表达式中,并且可以通过方法调用推断和返回类型。
Object obj = new Object() {
void fn() {
System.err.println("fn");
}
@Override public String toString() {
fn();
return "";
}
};
obj.toString();
new Object() {
void fn() {
System.err.println("fn");
}
}.fn();
identity(new Object() {
void fn() {
System.err.println("fn");
}
}).fn();
...
private static <T> T identity(T value) {
return value;
}
我班上的一个学生问我们的教授是否可以在前几天这样做。这是我写的很酷的概念证明,它可以做到,虽然不值得,但它实际上是可能的,这是如何做到的:
public static void main(String[] args){
//anonymous inner class with method defined inside which
//does not override anything
Object o = new Object()
{
public int test = 5;
public void sayHello()
{
System.out.println("Hello World");
}
};
//o.sayHello();//Does not work
try
{
Method m = o.getClass().getMethod("sayHello");
Field f = o.getClass().getField("test");
System.out.println(f.getInt(o));
m.invoke(o);
} catch (Exception e)
{
e.printStackTrace();
}
}
通过使用Java的Method类,我们可以通过传入方法的字符串值和参数来调用方法。字段也可以做同样的事情。
只是觉得分享这个会很酷!
,现在var
结构(Java 10或更高版本)允许这样做。例:
var calculator = new Object() {
BigDecimal intermediateSum = BigDecimal.ZERO;
void calculate(Item item) {
intermediateSum = Numbers.add(intermediateSum, item.value);
item.sum= intermediateSum;
}
};
items.forEach(calculator::calculate);
这里带有方法引用,但当然也适用于点方法调用。它也适用于字段。享受新的Java。:-)
我在这里发现了更多关于var
和匿名课程的技巧:https://blog.codefx.org/java/tricks-var-anonymous-classes/
您的调用方知道listener
是ActionListener
,因此它对该新方法一无所知。我认为做到这一点的唯一方法(除了做反射体操,这确实会破坏使用匿名类的目的,即快捷方式/简单性)是简单地子类ActionListener
而不使用匿名类。
不,这是不可能的。您需要将 ActionListener 强制转换为其真正的子类名称,但由于它是匿名的,因此它没有名称。
正确的方法是使用反射:
import java.lang.reflect.InvocationTargetException;
public class MethodByReflectionTest {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
Object obj = new Object(){
public void print(){
System.out.println("Print executed.");
}
};
obj.getClass().getMethod("print", null).invoke(obj, null);
}
}
您可以在此处查看:当给定方法名称为字符串时,如何调用 Java 方法?
是的,您可以访问该方法,请参阅下面的示例,如果有任何疑问,请发表评论
package com;
interface A
{
public void display();
}
public class Outer {
public static void main(String []args)
{
A a=new A() {
@Override
public void display() {
System.out.println("Hello");
}
};
a.display();
}
}