8

Let's say I have a class with a string field named "myfield", and use reflection to get the field, I've found that Object.getClass().getDeclaredField("myfield"); is case sensitive, it will throw an NoSuchFieldException if I for example use Object.getClass().getDeclaredField("MyField");

Is there any way around it? forcing it to ignore case?

Thanks

Dead Programmer
  • 12,427
  • 23
  • 80
  • 112
GoofyHTS
  • 263
  • 1
  • 6
  • 15
  • 2
    Beware that Java itself is case-sensitive so there may be 2 different fields which have same name when you do .toLowercase() on the name! – Jan Zyka Mar 18 '11 at 11:22
  • I'm aware of that, but in my case it's guaranteed not to happen – GoofyHTS Mar 18 '11 at 12:25

8 Answers8

18

Just use Class.getDeclaredFields() and look through the results performing a case-insensitive match yourself.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
4

No, there's no such way. You can get all fields and search through them:

Field[] fields = src.getClass().getDeclaredFields();
for(Field f:fields){
    if(f.getName().equalsIgnoreCase("myfield")){
    //stuff.
    }
}
secmask
  • 7,649
  • 5
  • 35
  • 52
2

The only way I see is to iterate over all declared fields and compare the names case-insensitively to the field name you are looking for.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
2

Get a list of all declared fields and manually go through them in a loop doing a case insensitive comparison on the name.

drekka
  • 20,957
  • 14
  • 79
  • 135
2

No, there is no direct way of doing this, however you could create a helper method for doing this. e.g. (untested)

public Field getDeclaredFieldIngoreCase( Class<?> clazz, String fieldName ) throws NoSuchFieldException {

        for( Field field : clazz.getDeclaredFields() ) {
            if ( field.getName().equalsIgnoreCase( fieldName ) ) {
                return field;
            }
        }
        throw new NoSuchFieldException( fieldName );
}
Danilo Tommasina
  • 1,740
  • 11
  • 25
1

I don't mean to necro this thread but if you used any of the methods above inside a loop your performance will be awful. Create map beforehand

first take the item your search for to uppercase

item.getKey()

now create a map that has the uppercase version and the true fieldnames

Map<String, String> fieldNames = Arrays.asList(clazz.getDeclaredFields()).stream().collect(Collectors.toMap(t -> t.getName().toUpperCase(), f->f.getName()));

now use that to grab the true fieldname

  Field field = clazz.getDeclaredField(fieldNames.get(key));

I would say always create such a map, always consider performance when it comes to reflection.

jdmneon
  • 444
  • 7
  • 12
  • If you only want to access one field for a particular class performance will be worse and there might be other situatuations. – lifesoordinary Sep 13 '18 at 13:02
0

Best to try to get field with fieldName if does not exist then loop through list of fields

public static Field findFieldIgnoreCase(Class<?> clazz, String fieldName) throws SecurityException, NoSuchFieldException {
    try {
        return clazz.getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.getName().equalsIgnoreCase(fieldName)) {
                return field;
            }
        }
        throw new NoSuchFieldException(fieldName);
    }
}
lifesoordinary
  • 123
  • 2
  • 9
-1

One thing to remember is to save the results of getDeclaredFields() this way you are only doing the reflection once use equalsIgnoreCase when you iterate. Reflection slows things down sometimes over 100x so anything you only have to do once, do once.

Field[] fields = MyClass.class.getDeclaredFields();
Field myField = null;
for (Field field : fields) {
    if (field.getName().equalsIgnoreCase("myField")) {
        myField = field;
        break;
    }
}
if (myField != null) {
    // do what you want with the found field
} else {
    //the field was not found and you wont get an error
}
jdmneon
  • 444
  • 7
  • 12