Method Reflection in Java

Is there any practical way to refer to a class method on a safe type? The main example is that I wanted to create something like the following utility function:

public Result validateField(Object data, String fieldName, 
                            ValidationOptions options) { ... }

To call, I would need to do:

validateField(data, "phoneNumber", options);

This forces me to use a magic string or declare a constant somewhere with that string.

I'm sure there is no way around this using the spare Java language, but is there some kind of pre-compiler (production class) or alternative compiler that can offer the job? (similar to how AspectJ extends the Java language) It would be nice to do something like the following:

public Result validateField(Object data, Method method, 
                            ValidationOptions options) { ... }

And name it with:

validateField(data, Person.phoneNumber.getter, options);
+5
source share
7

, ... , . , , . , , , ..

, , , .

, , :

public static Method lookupMethod( Class c, String name, Class... args ) {
    // do the lookup or throw an unchecked exception of some kind with a really
    // good error message
}

, , :

public class MyClass {
    private static final Method GET_PHONE_NUM = MyUtils.lookupMethod( PhoneNumber.class, "getPhoneNumber" );

    ....

    public void someMethod() {
        validateField(data, GET_PHONE_NUM, options);
    }
}

, , MyClass .

, bean, . bean, , , . - , .

+4

, , Java 7 .

, , .

+3

Java , - , Person.phoneNumber.getter. Person , getter . , CGLib, , Mockito.

MethodSelector<Person> selector = new MethodSelector<Person>(Person.class);
selector.select().getPhoneNumber();
validateField(data, selector.getMethod(), options);

Selector: https://gist.github.com/stijnvanbael/5965609

+2

http://jodd.org/doc/methref.html. - Jodd (Proxetta) - . , .

: , Str.class .boo(), "boo":

Methref<Str> m = Methref.on(Str.class);

// `.to()` returns a proxied instance of `Str` upon which you
// can call `.boo()` Methods on this proxy are empty except when
// you call them, the proxy stores the method name. So doing this
// gets the proxy to store the name `"boo"`.

m.to().boo();

// You can bget the name of the method you called by using `.ref()`:

m.ref();   // returns "boo"                                 

API , : http://jodd.org/api/jodd/methref/Methref.html

+2

- ?

, . , , .

, , , , . :

Method m;
if (arbitraryFunction(obj)) {
    obj.getClass().getDeclaredMethod("foo", ...);
} else {
    obj.getClass().getDeclaredMethod("bar", ...);
}

, ? NO, , arbitraryFunction(obj) . ( , , , ... AFAIK.)

, , Java- , .

, - -, Java. , "" , .


, . .. Person.class.getMethod("getPhoneNumber", null) , .

, , , Person, getPhoneNumber?

, , getPhoneNumber, - , - Person. Java. .

( , , , IncompatibleClassChangeError - , ...)

+1

, :

validator.validateField(data, options).getPhoneNumber();
Result validationResult = validator.getResult();

- :

class Validator {
    public <T> T validateField(T data, options) {...}
}

, ( ) , getter.

, , Getter , .

- :

class FooData {
    @Validate(new ValidationOptions(...))
    private PhoneNumber phoneNumber;
}

:

FooData data;
validator.validate(data);

.

0

picklock :

class Data {
  private PhoneNumber phoneNumber;
}

interface OpenData {
  PhoneNumber getPhoneNumber(); //is mapped to the field phoneNumber
}

Object data = new Data();
PhoneNumber number = ObjectAccess
  .unlock(data)
  .features(OpenData.class)
  .getPhoneNumber();

. , , . , unit test

 assertThat(Data.class, providesFeaturesOf(OpenData.class));
0

All Articles