我想要一个static
映射,其中值是实例方法。有些像:
public class MyClass {
static Map<MyEnum, Consumer<String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
}
这给了我一个错误,说“无法从静态上下文中引用非静态方法”。我理解为什么如果我试图从静态上下文中调用方法会出现问题,但是从实例方法中不可能从地图中检索方法并将其传递给this
?像:
MyClass.methodMapping.get(MyEnum.FIRST).accept(this, "string");
答案 0 :(得分:3)
这可以解决,就像将Consumer
更改为BiConsumer
一样简单,将MyClass
的接收器实例转换为函数的参数:
public class MyClass {
static Map<MyEnum, BiConsumer<MyClass,String>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, MyClass::firstMethod);
methodMapping.put(MyEnum.SECOND, MyClass::secondMethod);
}
void firstMethod(String param) {
...
}
void secondMethod(String param) {
...
}
void callTheMethod(MyEnum e, String s) {
methodMapping.get(e).accept(this, s);
}
}
答案 1 :(得分:2)
您在静态初始化块中初始化methodMapping
。此时,您的实例方法尚未被引用,因为您尚未调用new MyClass()
。
您可以通过将方法设置为静态,或将methodMapping初始化从静态块移动到构造函数来解决此问题。
PS:初始化块
中可以省略关键字 static答案 2 :(得分:1)
似乎你不明白
didFinishLaunchingWithOptions
正是如此,试图从他们不存在的静态上下文中调用这些方法。
这里要理解的关键是:您打算创建方法参考;并且方法引用需要一些对象来调用该方法。因此,没有&#34;延迟&#34 ;; java中没有办法表达&#34;等待launchOptions
有意义&#34 ;;或换句话说:在静态上下文中无法表达:&#34;稍后您将在非静态上下文中使用;然后从那里选择相应的didFinishLaunchingWithOptions
&#34;。
答案 3 :(得分:1)
是否可以从实例方法中从地图中检索方法并将其传递给
this
没有。 Consumer
只有一个参数accept()
方法,所以没有&#34;在通话时间传递this
&#34;。
创建方法引用时需要一个实例,因此这些问题归结为&#34;无法从静态上下文中调用实例方法&#34;。
答案 4 :(得分:1)
关键是推迟this
的规范或更具体:要调用方法的特定实例。因此,不是直接存储方法引用,而是存储接受实例的函数并返回该实例的方法引用。
<强> MyClass.java 强>
public class MyClass {
static Map<MyEnum, Function<MyClass, Consumer<String>>> methodMapping;
static {
methodMapping = new EnumMap<>(MyEnum.class);
methodMapping.put(MyEnum.FIRST, t -> t::firstMethod);
methodMapping.put(MyEnum.SECOND, t -> t::secondMethod);
}
private String id;
public MyClass(String id) {
this.id = id;
}
void firstMethod(String param) {
System.out.println(id + ", 1st method, " + param);
}
void secondMethod(String param) {
System.out.println(id + ", 2nd method, " + param);
}
void dispatchMethod(MyEnum myEnum, String param) {
methodMapping.get(myEnum).apply(this).accept(param);
}
}
<强> Main.java 强>
public class Main {
public static void main(String[] args) {
MyClass instance = new MyClass("MyInstance");
MyClass.methodMapping.get(MyEnum.FIRST).apply(instance).accept("Using mapping directly");
instance.dispatchMethod(MyEnum.SECOND, "Using dispatch method");
}
}
理想情况下,methodMapping
应该屏蔽其他类别的直接访问权限,因此我建议采用dispatchMethod
方法并使methodMapping
私有且不可变。