4

Suppose I have a class with a member variable int c. Suppose I also have a Field f. I want to check whether f represents c. I can do:

f.getName().equals("c")

but I'm looking for a solution such that if I were to rename c, the compiler would alert me in some way. Something like f == c.getField().

My guess is that there is no way to do this, but I'd like to confirm!

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
Sam
  • 151
  • 8
  • 3
    As far as I know, there is no way to do this. +1 – Martijn Courteaux May 27 '14 at 14:07
  • 2
    You can't do this. `Field` is a runtime representation of a class member, there's no way to check which class member are we talking about at compile-time. – Konstantin Yovkov May 27 '14 at 14:08
  • I don't think there is any way to do it without some recoding on rename, but you can minimize the risk of errors by putting some record of the field's identifier next to its declaration. For example, you could have a String variable containing the identifier. – Patricia Shanahan May 27 '14 at 14:11
  • 3
    Could you assert it in a unit test? That's more or less "compile time" – Bohemian May 27 '14 at 14:12
  • http://stackoverflow.com/questions/4485875/why-myclass-class-exists-in-java-and-myfield-field-isnt and other similar questions. – Sotirios Delimanolis May 27 '14 at 14:21
  • 1
    You *can't* check against a field's name, but you *can* check against its annotations, if you have the option to use them. – blgt May 27 '14 at 14:21

2 Answers2

0

Using the assert statement in combination with the -ea switch you can verify that the field's name remains the same.

Following the "Programming With Assertions" guidelines we can deduce that this is an applicable situation to use them:

Each assertion contains a boolean expression that you believe will be true when the assertion executes. If it is not true, the system will throw an error. By verifying that the boolean expression is indeed true, the assertion confirms your assumptions about the behavior of your program, increasing your confidence that the program is free of errors.

Exceptions are used to catch exceptional behaviour, assertions are used to verify invariant assumptions.

That being said: it was unclear from the problem description how your setup exactly looks like but this snippet will act the way I interpret it:

public class Main {
    int c = 5;

    public static void main(String[] args) {
        Field f = null;
        try {
            f = ReflectionTest.class.getDeclaredField("c");
        } catch (NoSuchFieldException | SecurityException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            return;
        }

        assert hasMember(f);

        System.out.println("We reached this point");
    }

    private static boolean hasMember(Field f) {
        for (Field localField : Main.class.getDeclaredFields()) {
            if (localField.getName().equals(f.getName())) {
                return true;
            }
        }

        return false;
    }
}

class ReflectionTest {
    int c = 10;
}

Using int c = 5; will simply print "We reached this point" while int a = 5; will show a nice error:

Exception in thread "main" java.lang.AssertionError
at Main.main(Main.java:38)
Jeroen Vannevel
  • 43,651
  • 22
  • 107
  • 170
0

There are no field literals like there are class literals. That basically means that the only way you can refer to a field is through a String value of its name. You won't be able to get IDE refactoring capabilities for fields, which I assume is why you want this.

public class Example {} ==> public class Refactored
... 
Example.class ==> Refactored.class // would cause compiler error if wasn't changed

You'll need to do this check at runtime, one way or another.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724