3

I'd like to implement a method that returns the field(s) from an interface that define a specified (int) value. I don't have source to the interface.

So, the signature could be something like this:

public ArrayList<String> getFieldnames(Object src, int targetValue);

And I'm assuming internally it could find the declared fields and test each against the value, returning the list.

ArrayList<String> s = new ArrayList<String>();

if( src!= null )
{
    Field[] flist = src.getClass().getDeclaredFields();
    for (Field f : flist )
        if( f.getType() == int.class )
            try {
                if( f.getInt(null) == targetValue) {
                    s.add(f.getName());
                    break;
                }
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            }
}
return s;

Unfortunately, this implementation is incorrect - it's as if there are no fields at all when called with the interface itself. If I pass an object that implements the interface, the list of possible fields will be too wide to be of use.

Thanks for any help!

1
  • See below for full answer. Use Class<?> src in signature and change calling site to pass in MyInterface.class. This avoids the internal getClass() and works like a charm! Commented May 8, 2013 at 0:03

3 Answers 3

3
public ArrayList<String> getFieldnames(Object src, int targetValue) {
  final Class<?> myInterfaceClass = MyInterface.class;
  ArrayList<String> fieldNames = new ArrayList<>();
  if (src != null) {
    for (Class<?> currentClass = src.getClass(); currentClass != null; currentClass = currentClass.getSuperclass()) {
      Class<?> [] interfaces = currentClass.getInterfaces();
      if (Arrays.asList(interfaces).contains(myInterfaceClass)) {
        for (Field field : currentClass.getDeclaredFields()) {
          if (field.getType().equals(int.class)) {
            try {
              int value = field.getInt(null);
              if (value == targetValue) {
                fieldNames.add(field.getName());
              }
            } catch (IllegalAccessException ex) {
              // Do nothing. Always comment empty blocks.
            }
          }
        }
      }
    }
  }
  return fieldNames;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Accepting this as the answer since it's the closest other than my own and it reminded me of the Class<?> typespec! Thanks!
0

This

src.getClass()

returns src class not interface. Consider this

interface I {
}

class A implements I {
}

new A().getClass() -- returns A.class 

2 Comments

Exactly! I'm trying to figure out how to pass in the interface so I can parse it. I cannot call getFieldNames(I, aField), I cannot call getFieldNames( new I(){}, aField ) (although that last one compiles) - how do I pass in the interface object to the method?
You can get all interfaces from the object class -> src.getClass().getInterfaces(), or simply pass it as MyInterface.class
0

Although I would rather have passed in an object, I suppose changing the signature to a string value and passing in the FQIN gets the job done just as well.

Thanks to <this question> for the idea (and Google for directing me there).

Solution:

public ArrayList<String> getFieldnamesByValue(Class<?>x, int targetValue)
{
    ArrayList<String> s = new ArrayList<String>();

    if( x != null )
    {
        Field[] flist = x.getDeclaredFields();
        for (Field f : flist )
            if( f.getType() == int.class )
                try {
                    if( f.getInt(null) == targetValue) {
                        s.add(f.getName());
                        break;
                    }
                } catch (IllegalArgumentException e) {
                } catch (IllegalAccessException e) {
                }
    }
    return s;
}

2 Comments

You don't need to use the fully qualified name. Just remove String interfaceFQName from the signature, remove that first try/catch, and replace it with Class<?> x = MyInterface.class;
That's the key, Alvin. I changed the signature of the method to getFieldnames(Class<?>src, int targetValue) so the body can just get straight into the loop. At the calling site, I can just quickly nail in ArrayList<String> names = getFieldNames(SOBConstants.class, 45) and voila!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.