【问题标题】:Pass method reference from different subclasses传递来自不同子类的方法引用
【发布时间】:2021-06-21 22:27:48
【问题描述】:

我目前正忙于弄清楚方法引用的工作原理。这就是我想要实现的目标。

User user = new User(...);
user.getValue(ADerived::getPropertyFromA);
user.getValue(BDerived::getPropertyFromB);

ADerived 和 BDerived 如下(简化)

public abstract class Base { }

public class ADerived extends Base {
    private static final String A_OUTPUT = "Test A";

    public String getPropertyFromA() {
        return A_OUTPUT;
    }
}

public class BDerived extends Base {
    private static final String B_OUTPUT = "Test B";

    public String getPropertyFromB() {
        return B_OUTPUT;
    }
}

getPropertyFromX 方法不是故意在 Base 类中定义的,因为它们差别很大。

在 BaseUser 类中,我将子类的一个实例保存在映射中,并尝试在该实例上执行传递的方法。至少这段代码可以编译,但当然不能按预期工作。 Function<> 周围的其他方法也不适用于我。

public class User {
    public Map<Class, Base> map;

    public User(...) {
        ... creates instances of ADerived and BDerived, puts them into map
    }

    ...

    public <R> String getValue(Function<R, String> func) {
        return func.apply((R) map.get((R) Base.class));
    }
}

由于多种原因,这显然不起作用,但我想不出一种方法来获得上述用法。

获得所描述的用法是否现实?我有什么遗漏吗?

很想听听想法或获得帮助。

【问题讨论】:

  • 当密钥始终相同 (Base.class) 时,你怎么能假设它映射到需要任意 R 的函数的适当输入?

标签: java java-8 method-reference


【解决方案1】:

您目前的做法是不可能的。 This answer 解释的很好。

但是,您可以这样做:

class User {
    // ...

    public <C extends Base> String getValue(Class<C> cls, Function<C, String> func) {
        return func.apply(cls.cast(map.get(cls)));
    }
}

class Main {
    public static void main(String[] args) {
        User user = new User();
        String value;
        
        value = user.getValue(ADerived.class, ADerived::getPropertyFromA);
        System.out.println(value); // Outputs Test A
        
        value = user.getValue(BDerived.class, BDerived::getPropertyFromB);
        System.out.println(value); // Outputs Test B 
    }
}

或者,如果你想避免重复类名,你可以使用方法名作为字符串。 注意:这种方法将失去编译时检查并使用反射,但我将其放在这里只是为了完整性。

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

// ...

class User {
    // ...

    public <C extends Base> String getValue(Class<C> cls, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        final Method method = cls.getMethod(methodName);
        return (String) method.invoke(map.get(cls));
    }
}

class Main {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        User user = new User();
        String value;
        
        value = user.getValue(ADerived.class, "getPropertyFromA");
        System.out.println(value); // Outputs Test A
        
        value = user.getValue(BDerived.class, "getPropertyFromB");
        System.out.println(value); // Outputs Test B 
    }
}

你应该处理

  • NoSuchMethodException当方法名在给定类中不存在时;

  • IllegalAccessException当试图访问的方法是受保护的或私有的;

  • InvocationTargetException 当方法被访问时抛出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多