javareflectionparametersfinalmodifiers

Is it possible to determine by reflection if method parameter is final?


Is it possible to find out, if the parameter of method is final? I have tried this:

int modifiers = method.getParameters()[0].getModifiers() // modifiers == 0

But even if first parameter has final modifier, modifiers is set to zero.

edit: I really don't think that my question is a duplicate. When I try this code with members of class (such as fields, methods, etc.), it works perfectly. But with method parameters getModifiers fails!

edit2: In questions you suggested me as similar I didn't find an answer... So could you help me, how to check if parameter is final?


Solution

  • After a brief study I am afraid that it is not possible. See first comment on this question

    If you looked at a decompiled class, you could see that the compiler erases the final keyword from all final parameters. And it is reasonable because the final makes sense only at compile time.

    I tried to find more proof on this but failed on that. Anyway I made a small test based on the 1st suggested dubes answer.

    Having test class like

    public class TestClass {
       public void testMethod(final Integer param) {} // could be also int
    }
    

    and running this test/logging

    @Test
    public void testIsFinal() throws NoSuchMethodException, SecurityException {
       Method method = TestClass.class.getMethod("testMethod", Integer.class);
       log.info("method {}", method);
       Parameter[] params = method.getParameters();
       log.info("params {}", params);
       log.info("params[0] {}", params[0]);
       log.info("modifiers {}", params[0].getModifiers());
       log.info("final {}", Modifier.isFinal( params[0].getModifiers() ));
    }
    

    logs

    2017-12-11 13:11:24.512 INFO org.example.jpa.JUnitTest:33 - method public void org.example.jpa.JUnitTest$TestClass.testMethod(java.lang.Integer)
    2017-12-11 13:11:24.521 INFO org.example.jpa.JUnitTest:36 - params[0] java.lang.Integer arg0
    2017-12-11 13:11:24.521 INFO org.example.jpa.JUnitTest:37 - modifiers 0
    2017-12-11 13:11:24.522 INFO org.example.jpa.JUnitTest:38 - final false

    so it seems that the only allowed method parameter modifier final does not exist in compiled method declaration. Note that it neither exists in logged methods signature

    public void org.example.jpa.JUnitTest$TestClass.testMethod(java.lang.Integer)
    

    From source code of Modifier

    public static final int FINAL            = 0x00000010;
    

    and

    /**
      * The Java source modifiers that can be applied to a method or constructor parameter.
      * @jls 8.4.1 Formal Parameters
      */
     private static final int PARAMETER_MODIFIERS = Modifier.FINAL;
    

    and

    public static boolean isFinal(int mod) {
       return (mod & FINAL) != 0;
    }
    

    so to tell that method parameter was declared as final the second bit should be 1.