Java method pass reference as a parameter for another method

I'm trying to pass the selected get get method of class A to class B. I checked the Java Pass Method as a parameter , but I could not take the interface approach to my problem in a reasonable way. I would prefer not to use java 8 (lambdas) and, if possible, avoid reflection. I feel that I am misunderstanding my problem. Here is a specific simplified example of what I'm trying to accomplish:

I have a class containing some fields and get methods:

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; } } 

Then I have a main instance of the DataStore class as map values, and then access to specific fields of the DataStore, for example:

 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, eg 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; } } 

Obviously this will not work, since I need to figure out how to pass the selected get method to getValuesAsArray() . Be that as it may, my approach may be wrong. Therefore, I am open to suggestions.

+5
source share
5 answers

Your getX() methods can be thought of as a function that takes an instance of a DataStore and returns a float.

In Java 8, you can represent them using method references:

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

Then your getValuesAsArray will take a Function<DataStore,Float> parameter and execute the function:

 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; } 

Without using Java 8, you can define your own interface containing a method that takes an instance of a DataStore and returns a float . Then, instead of using Java 8 method getValuesAsArray you need to pass your getValuesAsArray method getValuesAsArray implementation of this interface (you can use an anonymous class instance that implements the interface) that calls one of the getX() methods.

For instance:

 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();}}); 

and

 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; } 
+6
source

I recently used java.util.concurrent.Callable, but it does not seem to work thanks to @Eran.

Instead, you can use Java 8 java.util.function.Function , for example (without lambdas):

 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; } 
+2
source

MethodReference is a class for the purpose of reflection. Your code really needs a lambda-like object, which should be the only method interface in Java 8.

Without Java 8 or reflection, there is no way to direct your need. But you can always pass some internal representation of the method to other callas, and for this you need to write code to process this internal representation.

0
source

Workaround: Scala java apis.

I use Apache Spark, and Scala offers a series of anonymous functions (Function, Function2) that are available with Java 1.5, if I'm not mistaken (although I use it with Java 1.7). Here is the answer saying this . Since otherwise the class "Function" is only available with Java 1.8

0
source

All Articles