89

I'm getting a java.lang.NoSuchFieldException when trying to run the following method:

 public void getTimes(String specialty, String day) {
    ArrayList<Tutor> withSpec = new ArrayList<Tutor>();
    for (Tutor t : tutorList){
        try {
            Time startTime = (Time)t.getClass().getField(day + "Start").get(t);
        } catch (NoSuchFieldException | SecurityException | IllegalAccessException ex) Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex); }

The error is on the line Time startTime = (Time)t.getClass().getField(day + "Start").get(t);

I don't understand this error, because monStart is a field of the Tutor class:

Public class Tutor implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "tutorID")
private Integer tutorID;

.... 

@Column(name = "monStart")
@Temporal(TemporalType.TIME)
 Date monStart;

I'm just learning to use reflection, so I'm sure this is some sort of a syntactical error...

drew moore
  • 31,565
  • 17
  • 75
  • 112

6 Answers6

174

The getField method will only find the field if it's public. You will need to use the getDeclaredField method instead, which will find any field that is declared directly on the class, even if it's not public.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • 1
    even after using getDeclaredField over getField iam getting this error :- can not access a member of class with modifiers "private" – Subodh Bisht Jan 29 '15 at 06:02
  • 10
    ohh get it. i need to use setAccessible(true) – Subodh Bisht Jan 29 '15 at 06:38
  • 5
    I am getting `NoSuchFieldException` even when using `getDeclaredField()`, and the "has private access" error even after using `setAccessible(true)`. **Example 1**: `Field fieldy = rootElement.getClass().getDeclaredField("name");` throws `NoSuchFieldException`. But doing `Field[] fields = rootElement.getClass().getDeclaredFields();` allows me to iterate through the fields, and when I call `field.getName()`, it returns "name". So what's the deal? – Joe Flack Sep 07 '18 at 20:13
  • 2
    **Solved**: Looks like I had to wrap in a try/catch – Joe Flack Sep 07 '18 at 20:26
  • 2
    @JoeFlack how did surrounding with a `try/catch` solve anything? The Exception gets thrown anyways, and then what do you do in the `catch` to properly get that field which exists but somehow throws the `NoSuchFieldException` ? – payne Nov 12 '21 at 17:03
  • 1
    If the field is inherited from a superclass, this answer won't be sufficient. See https://stackoverflow.com/a/69946642/9768291 – payne Nov 12 '21 at 17:13
13

According to the javadoc, Class.getField() "Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object". Use getDeclaredField() if you want to access non-public fields.

Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
9

For any Android developers seeing this that still can't seem to fix the issue, check to see if Proguard is enabled. If it is, it's possible the class in question is being obfuscated and you'll need to add rules to prevent that from happening.

Brian Yencho
  • 2,748
  • 1
  • 18
  • 19
  • Thanks a lot. My class was also getting obfuscated. I had to disable `minifyEnabled` flag in order to prevent it. – theimpulson Oct 12 '21 at 11:42
8

Best solutions for getClass().getField() problem are:

  1. Use getDeclaredField() instead of getField():
        String propertyName = "test";
        Class.forName(this.getClass().getName()).getDeclaredField(propertyName);
  1. Replace "HelloWorld" with your class name:
        String propertyName = "name";
        HelloWorld.class.getDeclaredField(propertyName);

If you want to get the annotation length of the column:

HelloWorld.class.getDeclaredField(propertyName).getAnnotation(Column.class).length();
payne
  • 4,691
  • 8
  • 37
  • 85
4

As mentioned in the accepted answer, using getDeclaredField will potentially solve your problem (in case the field wasn't declared as public).

If you are still getting the NoSuchFieldException, then it might be because that field is actually in the superclass! Indeed, if your class extends another class, then you will not get the inherited fields through the getDeclaredField method. Here is how to fix that problem:

String propertyName = "foo";
yourClass.getClass().getSuperClass().getDeclaredField(propertyName);
payne
  • 4,691
  • 8
  • 37
  • 85
2

I came to this question based on the title. I was getting the same error (NoSuchFieldException) in my Android project but for a different reason.

So for others who come here, this error can also potentially be caused by the caches getting out of sync in Android Studio. Go to File > Invalidate Caches / Restart...

See this also

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393