Java 将方法引用作为参数传递给其他方法

2022-09-02 12:13:41

我正在尝试将类 A 的选定“get”方法传递给类 B 中的方法。我已经检查了Java Pass方法作为参数,但我无法以合理的方式采用接口方法来解决问题。我宁愿不使用java 8(lambdas),如果可能的话,也避免反射。我的感觉是,我以错误的方式看待我的问题。以下是我试图完成的具体简化示例:

我有一个包含一些字段和get方法的类:

public class DataStore {
    private float a;
    private float b;
    private float c;

    public float getA() {
        return a;
    }

    public float getB() {
        return b;
    }

    public float getC() {
        return c;
    }

}

接下来,我将主类实例化为 Map 的值,然后访问 DataStore 的特定字段,例如:DataStore

public class App {

    public static void main(String[] args) {
        // declare TreeMap using DataStore class as value
        Map<Integer, DataStore> dataMap = new TreeMap<Integer, DataStore>();

        // populate Map with example data
        dataMap.put(2,  new DataStore(1f,2f,3f));
        dataMap.put(10, new DataStore(3f,4f,5f));
        dataMap.put(4,  new DataStore(6f,7f,8f));

        // work with specific fields in DataStore, e.g. assign to array
        float[] aArray = getValuesAsArray(dataMap, DataStore.getA());
        float[] bArray = getValuesAsArray(dataMap, DataStore.getB());
        float[] cArray = getValuesAsArray(dataMap, DataStore.getC());
    }

    /**
     * Assign specific field of DataStore from Map to Array
     * @param dataMap
     * @param getVar - reference for specified getter method
     * @return 
     */
    private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, MethodReference getVar()) {
        int i = 0;
        int nMap = dataMap.size();
        float[] fArray = new float[nMap];
        for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
            DataStore ds = entry.getValue();
            fArray[i] = ds.getVar();
            i++;
        }
        return fArray;
    }
}

显然,这不起作用,因为我必须弄清楚如何将我选择的get方法传递到.不知何故,我想,我的方法可能是错误的。因此,我愿意接受建议。getValuesAsArray()


答案 1

您的方法可以看作是一个接受 DataStore 实例并返回浮点数的函数。getX()

在Java 8中,你可以用方法引用来表示它们:

    float[] aArray = getValuesAsArray(dataMap, DataStore::getA);
    float[] bArray = getValuesAsArray(dataMap, DataStore::getB);
    float[] cArray = getValuesAsArray(dataMap, DataStore::getC);

然后,您将接受一个参数并执行该函数:getValuesAsArrayFunction<DataStore,Float>

private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, Function<DataStore,Float> func) {
    int i = 0;
    int nMap = dataMap.size();
    float[] fArray = new float[nMap];
    for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
        DataStore ds = entry.getValue();
        fArray[i] = func.apply(ds);
        i++;
    }
    return fArray;
}

在不使用 Java 8 的情况下,您可以定义自己的接口,其中包含接受实例并返回 .然后,您必须向该接口的实现(您可以使用实现该接口的匿名类实例)传递给您的方法,而不是使用 Java 8 方法引用,该实现该接口调用其中一个方法。DataStorefloatgetValuesAsArraygetX()

例如:

public interface ValueGetter
{
    public float get (DataStore source);
}

float[] aArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getA();}});
float[] bArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getB();}});
float[] cArray = getValuesAsArray(dataMap, new ValueGetter() {public float get (DataStore source) {return source.getC();}});

private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, ValueGetter func) {
    int i = 0;
    int nMap = dataMap.size();
    float[] fArray = new float[nMap];
    for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
        DataStore ds = entry.getValue();
        fArray[i] = func.get(ds);
        i++;
    }
    return fArray;
}

答案 2

不久前,我使用了java.util.concurrent.Callable,但由于@Eran,它似乎不起作用。

相反,您可以使用Java 8的,如下所示(没有lambdas):java.util.function.Function

public static void main(String[] args) {
 //...
    getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getA(); }});
    getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getB(); }});
    getValuesAsArray(dataMap, new Function<DataStore,Float>(){ public Float apply(DataStore input) { return input.getC(); }});
}

private static float[] getValuesAsArray(Map<Integer, DataStore> dataMap, Function<DataStore, Float> function) {
    int i = 0;
    int nMap = dataMap.size();
    float[] fArray = new float[nMap];
    for (Map.Entry<Integer, DataStore> entry : dataMap.entrySet()) {
        DataStore ds = entry.getValue();
        fArray[i] = function.apply(ds);
        i++;
    }
    return fArray;
}