Можно ли путем отражения определить, является ли параметр метода окончательным?

Можно ли узнать, если параметр метода равен final? Я пробовал это:

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

Но даже если первый параметр имеет модификатор final, modifiers устанавливается равным нулю.

редактировать: я действительно не думаю, что мой вопрос является дубликатом. Когда я пробую этот код с членами класса (такими как поля, методы и т. д.), он работает отлично. Но с параметрами метода getModifiers не работает!

edit2: В вопросах, которые вы предложили мне как похожие, я не нашел ответа... Не могли бы вы мне помочь, как проверить, является ли параметр окончательным?


person oquechy    schedule 10.12.2017    source источник
comment
Просто интересно: зачем тебе это?   -  person JB Nizet    schedule 10.12.2017
comment
@Ivonet Я тоже так думал, но нет. Речь идет о параметрах метода. название немного вводит в заблуждение.   -  person pirho    schedule 10.12.2017
comment
Я думаю, что этот ответ тесно связан. Использование предложенного метода дублирования возвращает 0, когда он должен возвращать 16 для final, что приводит к isFinal()=false.   -  person pirho    schedule 10.12.2017
comment
На самом деле вопрос очень близок к тому, чтобы быть дубликатом этого вопроса, даже с точки зрения аннотации.   -  person pirho    schedule 10.12.2017


Ответы (1)


После краткого изучения боюсь, что это невозможно. См. первый комментарий к этому вопросу.

Если вы посмотрите на декомпилированный класс, то увидите, что компилятор стирает ключевое слово final из всех конечных параметров. И это разумно, потому что финал имеет смысл только во время компиляции.

Я пытался найти больше доказательств этого, но потерпел неудачу. В любом случае, я сделал небольшой тест, основанный на первом предложенном ответе.

Имея тестовый класс, как

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

и запуск этого теста/регистрации

@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() ));
}

журналы

2017-12-11 13:11:24.512 ИНФОРМАЦИЯ org.example.jpa.JUnitTest:33 — метод public void org.example.jpa.JUnitTest$TestClass.testMethod(java.lang.Integer)
2017-12-11 13:11:24.521 ИНФОРМАЦИЯ org.example.jpa.JUnitTest:36 - params[0] java.lang.Integer arg0
2017-12-11 13:11:24.521 ИНФОРМАЦИЯ org.example.jpa.JUnitTest:37 - модификаторы 0
2017-12-11 13:11:24.522 INFO org.example.jpa.JUnitTest:38 - final false

поэтому кажется, что единственный разрешенный модификатор параметра метода final не существует в объявлении скомпилированного метода. Обратите внимание, что он не существует в сигнатуре зарегистрированных методов.

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

Из исходный код Modifier

public static final int FINAL            = 0x00000010;

а также

/**
  * 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;

а также

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

поэтому, чтобы сказать, что параметр метода был объявлен как final, второй бит должен быть равен 1.

person pirho    schedule 10.12.2017