0

In C# we can obtain a property, field or method name in runtime, like below:

Condition<UserEntity, bool>(v => v.Locked);

where Locked is one of UserEntity properties and v=>v.Locked will be sent to a method and finally we can get name of property as string "Locked".

below is Condition signature:

public void Condition<EntityT, ObjectT>(
    Expression<Func<EntityT, object>> propertyExpression
)

Method to obtain property name is:

public static string GetPropertyName<T>(this Expression<Func<T, object>> expression)
{
    MemberExpression memberExpression = null;
    if (expression.Body.NodeType == ExpressionType.Convert) {
        var body = (UnaryExpression)expression.Body;
        memberExpression = body.Operand as MemberExpression;
    } else if (expression.Body.NodeType == ExpressionType.MemberAccess) {
        memberExpression = expression.Body as MemberExpression;
    }
    if (memberExpression == null) {
        throw new ArgumentException("Not a member access", "member");
    }
    string text = memberExpression.ToString();
    return text.Substring(text.IndexOf('.') + 1);
}

Is there any way o obtain field or method names like above but in Java?

Edit

I developed below method, but this method works somewhere and does not work somewhere, so this is not final answer, if anyone can help me fix problems with this method

public interface SerializableConsumer<THolder> extends Consumer<THolder>, Serializable {}

 * detects and returns name of back field from getter method
 * @param getter getter method to start finding backfield name
 * @return name of backfield
 */
public static String getterFieldName(SerializableConsumer<?> getter) {
    for (Class<?> cl = getter.getClass(); cl != null; cl = cl.getSuperclass()) {
        try {
            Method writeReplaceMethod = cl.getDeclaredMethod("writeReplace");
            writeReplaceMethod.setAccessible(true);
            Object replacement = writeReplaceMethod.invoke(getter);
            if(!(replacement instanceof SerializedLambda))
                break;// custom interface implementation
            SerializedLambda serializedLambda = (SerializedLambda) replacement;
            String getterName = serializedLambda.getImplMethodName();
            if(!getterName.startsWith("get"))
                throw new RuntimeException("getter name must start with 'get'");
            String rawFieldName = getterName.substring("get".length());
            String firstChar = rawFieldName.substring(0, 1);
            String wordRest = rawFieldName.substring(1);
            String fieldName = firstChar.toLowerCase() + wordRest;
            return fieldName;
        }
        catch (NoSuchMethodException e) {}
        catch (IllegalAccessException | InvocationTargetException e) {
            break;
        }
    }
    throw new RuntimeException("Can not find field");
}
Homayoun Behzadian
  • 1,053
  • 9
  • 26
  • 1
    In Java, when we want the string `"Locked"`, we use `"Locked"`. Seriously, when you request a function mapping from `UserEntity` to `boolean`, be it `Predicate` or `Function` or whatever functional interface you like, there is no requirement that the implementation is a named property. It can be an ordinary class, an anonymous class, a proxy, a method reference or a lambda expression. Only one of them directly maps to a named entity, all others may contain arbitrary code. – Holger Jul 24 '19 at 13:03
  • 2
    Related: [Printing debug info on errors with java 8 lambda expressions](https://stackoverflow.com/q/21860875/2711488), [How to get the MethodInfo of a Java 8 method reference?](https://stackoverflow.com/q/19845213/2711488), [Reflection type inference on Java 8 Lambdas](https://stackoverflow.com/q/21887358/2711488)… – Holger Jul 24 '19 at 13:09
  • @Holger, question you mentioned helped me, I think you got my mean, I need to get a method name that throws error during compile if it does not exists. – Homayoun Behzadian Jul 27 '19 at 06:40

0 Answers0