1

I'm trying to tell whether a a field's value in a Java class is set on declaration or within a constructor body.

Consider the following code for Case Declaration:

class MyClass {
    int myField = 42;   // myField is initialized on declaration
    MyClass() {
        // this constructor is **not** setting myField
    }
}

versus Case Constructor:

class MyClass {
    int myField;      // myField is initialized on declaration with base value (0)
    MyClass() {
        myField = 42; // myField gets value on constructor
    }
}

Rephrasing my question: by using reflection can I tell whether I'm on Case Declaration or on Case Constructor, and if so, how?

The closest I've got is getting the field value from an instance (for example on this question) But that requires instantiation, so I finally get the value 42 in both cases.

The code for that could be something like:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    Field field = MyClass.class.getDeclaredField("myField");
    MyClass instance = new MyClass();
    System.out.println("myField: " + field.get(instance));  // it writes 42 in both cases
}

I could parse both classes' source code but that would require adding some complexities to the workflow I'd rather avoid.

In case you want some context, I'm teaching an introductory course on OOP using Java, and I provide my students some JUnit code to check whether their solutions meet the requirements. In this concrete case I'm trying to force them to start using constructor's initialization for their first time.

ANSWERED: it is not possible to tell at runtime (see @Sweeper's comment) since both versions result in exactly the same bytecode.

Moisès
  • 37
  • 7
  • 5
    You can't tell at runtime. The class files are the same. This sounds like a problem better checked at compile time. How about asking your students to run a static analyser? – Sweeper Mar 18 '21 at 10:32
  • 2
    For example, you can write a custom check for this using [checkstyle](https://checkstyle.sourceforge.io/writingchecks.html). – Sweeper Mar 18 '21 at 10:35
  • What makes you think you can do that? This is a **source code representation** problem. No sense in trying to solve it at *runtime*. – GhostCat Mar 18 '21 at 10:40
  • @Sweeper comment is definitive. Both cases resulting bytecodes (``java -c``) are the same so there's no way to tell on runtime. The style checker suggestion opens a whole world of possibilities for my workflow. I'm so grateful for all that! – Moisès Mar 18 '21 at 11:15
  • Don't use reflection to check the internal implementation - that's bad style and breaks encapsulation. (Clients should NOT care how the information is stored.) – Johannes Kuhn Mar 18 '21 at 12:30
  • Thanks @JohannesKuhn . While it is a good advice in general, this use of JUnit is for educational purpose. Learners get a quick feedback on their code. – Moisès Mar 18 '21 at 13:28
  • 1
    Yeah, I have seen unit tests that check if certain fields exist - and enforce the name of them. Some unit test also checked that there is a `setFoo` method - but that method was never called/tested. And because the body of the set function was empty, it's good practice to declare the fields final. Which was again prevented by the use of reflection. Simply use some static code analysis tool for stuff like that. – Johannes Kuhn Mar 18 '21 at 15:09

0 Answers0