0

As far as my understanding goes, method references can be used either statically or with wrapped object instance, for example:

public class MethodReferencesExampleTest {

    class Example {
        private String variable;

        public Example(String variable) {
            this.variable = variable;
        }

        public String getVariable() {
            return variable;
        }
    }

    @Test
    public void shouldBeAbleToUseBothClassAndInstanceMethodReference() {
        Example objectUnderTest = new Example("variable");

        useClassMethodReference(Example::getVariable, objectUnderTest);
        useInstanceMethodReference(objectUnderTest::getVariable);
    }

    private <T> void useClassMethodReference(Function<T, String> methodReference, T object) {
        System.out.println("Class reference call result = " + methodReference.apply(object));
    }

    private void useInstanceMethodReference(Supplier<String> methodReference) {
        System.out.println("Instance reference call result = " + methodReference.get());
    }

}

What I would like to do is extract instance method reference and somehow convert it to class method reference, so that I could apply it to a different object of the same class, like:

private <T> void useInstanceMethodReferenceOnDifferentObjectThanItsSource(Supplier<String> instanceMethodReference, T object) {
    Function<T, String> classMethodReference = /* some magical conversion */ instanceMethodReference;
    System.out.println("Instance reference call result = " + classMethodReference.apply(object));
}

Is it at all possible? Byte-code wizardry like using cglib or even shady "hacks" are an acceptable answer.

Jezor
  • 3,253
  • 2
  • 19
  • 43
  • 5
    Could you give some context for why this is necessary? There seems to be an [XY Problem](http://xyproblem.info). – 4castle Dec 16 '16 at 20:20
  • @4castle I am trying to implement validation with fluent API. I am obtaining the validated object as the first step, and then I'm using getters to validate fields. I need to use `Function` though, as it allows me to get the method name. It would be nice to write `validate(validatedObject::getField)` instead of `validate(ValidatedObjectClass::getField)`. – Jezor Dec 16 '16 at 20:41
  • 2
    A bound instance method ref is exactly that -- bound to a receiver. If you want a method ref unbound to a receiver, use an unbound instance method ref (`ClassName::instanceMethod`). There's no (reasonable) way to "take apart" a lambda or mref and put it back together differently. – Brian Goetz Dec 17 '16 at 20:35
  • @BrianGoetz I'm fine with unreasonable ways too, if you know any (; – Jezor Dec 17 '16 at 23:33
  • 1
    Use unbound method references. That's what they're there for. – Brian Goetz Dec 18 '16 at 15:00
  • 1
    Just look at the method signature of your example and think about what you are asking for. You receive an arbitrary `Supplier` and expect it to represent of a property of `T`. What’s the foundation of that expectation? The provided `Supplier` could be just `() -> "hello"` or even an ordinary class instead of a lambda expression’s representation. – Holger Dec 19 '16 at 11:37
  • You are looking for "unreasonable ways too". Why can't you just forget the functional interfaces and use reflections instead? – RajatJ Apr 14 '17 at 14:22
  • @RajatJ I've end up using this trick - https://github.com/benjiman/benjiql/tree/master/src/main/java/uk/co/benjiweber/benjiql/mocking – Jezor Apr 19 '17 at 00:43

0 Answers0