[java 5] так как все таки правильно передавать null в var-arg функцию?

pitrik2

в 4 java было: method.invoke(obj, null);
в 5 как должно стать?
есть официальная рекомендация sun?
а другие компиляторы так же будут работать, например ibm 1.5?

bastii

объясни, я не понял твой вопрос

Svyatogor

Тоже не понял вопрос. В частности - что изображено в примерах? Вызов метода через reflection (method - это метод с variable arity parameter во время компиляции или invoke - это тот самый vararg метод? В 1.4 же не было методов с произвольным числом параметров.
От Sun есть спецификация языка Java, где описано, чем на самом деле является метод с переменным числом параметров и как он должен вызываться. См. главы 15.12 (особенно 15.12.4.2) и 8.4.1 из Java Language Specification, Third Edition. Кроме того, в главе 13.1 идет ссылка на спецификацию The Java Virtual Machine Specification (которая практически не менялась при переходе к 1.5). Соответственно компилятор должен следовать всем этим правилам.

pitrik2

попытаюсь объяснить
смотрим 1.4
If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null.
т.е. можно писать так: method.invoke(obj, null);
смотрим 1.5
If the number of formal parameters required by the underlying method is 0, the supplied args array may be of length 0 or null.
тоесть описание совпадает, но method.invoke(obj, null); - не компилится, выдает ворнинг
C:\...\DynaValidatorForm.java (54:110) non-varargs call of varargs method with inexact argument type for last parameter;
C:\...\DynaValidatorForm.java warning: non-varargs call of varargs method with inexact argument type for last parameter;
cast to java.lang.Object for a varargs call
cast to java.lang.Object[] for a non-varargs call and to suppress this warning
это же наверное не единственный пример, когда в 1.4 была функция с массивом параметров, а в 1.5 ее сделал вараргнутой
вариантов три, какой из них правильно выбирать в таких случаях и чем они отличаются не очень понятно
1) method.invoke(obj)
2) method.invoke(obj, (Object)null)
3) method.invoke(obj, (Object[])null)

bastii

2) и 3) будут в 1.4 компиляторе работать, мне кажется, что 3) более ясный

pitrik2

2) и 3) будут в 1.4 компиляторе работать, мне кажется, что 3) более ясный
2) в 1.4 компилится не будет
что значит более ясный? как ясность с правильностью соотносится?

Svyatogor

тоесть описание совпадает, но method.invoke(obj, null); - не компилится, выдает ворнинг
Компайлится. Warning и Error - разные вещи. При warning'ах class-файл все равно создается.
вариантов три, какой из них правильно выбирать в таких случаях и чем они отличаются не очень понятно
1) method.invoke(obj)
2) method.invoke(obj, (Object)null)
3) method.invoke(obj, (Object[])null)
Эти случаи эквивалентны следующему:
1) method.invoke(obj, new Object[]{}); //т.е. вызову с пустым массивом.
2) method.invoke(obj, new Object[]{null}); //т.е. если речь идет о reflection, будет вызов метода с 1-м параметром, что во время ошибки приведет к IllegalArgumentException
3) method.invoke(obj, null); // т.е. то, что выдает предупреждение (исходный пример работает аналогично тому, что написано в 3-м случае.
Предупреждение как раз и выдается, чтобы не путать 2-ю и 3-ю трактовку. В целом же разбор выражений сделан обратно совместимым с предыдущей редакцией.
По 3-ей спецификации по пунткам случаи будут скомпилированы по следующим пунктам
1) 15.12.2.4
2) 15.12.2.4 (под 15.12.2.3 не попадает, так как Object не преобразуется при вызове метода к (Object[]
3) и исходный пример 15.2.2.3.
Ну и дальше делается соответствующий вызов по пункту 15.12.4.2
Что лучше писать - зависит больше от личных предпочтений. Очевидно, не 2-й случай (не тот результат) и не исходный (может вызвать неоднозначную трактовку при чтении). Среди 1 и 3 - если есть возможность, что код будет компилироваться под 1.4 или ранее - нужно выбирать 3-й (единственно возможный). Если же будет компилироваться под 1.5 и выше, я бы выбрал 1-й вариант. Причины следующие:
1) Для цепочки method.invoke(obj, v1, v2, v3 method.invoke(obj, v1, v2 method.invoke(obj, v1) более логично продолжение method.invoke(obj) (создание лишнего объекта в большинстве случаев практически не заметно).
2) Из общих соображений, что пустая коллекция обычно лучше, чем null. Использование пустых коллекций (и массивов) позволяет их обрабатывать точно так же, как и непустые. Если же представлять пустую коллекцию как null, нужно будет делать дополнительную проверку (хотя для java.lang.reflect.Method.invoke(Object, Object[]) такой вызов явно допускается, что-нибудь другое может упасть в таком случае с NullPointerException).

bastii

2) в 1.4 компилится не будетчто значит более ясный? как ясность с правильностью соотносится?
ок, ступил, посмотрел что массив приводится к Object, а там надо в др сторону — тогда остается единственный вариант, который работает с компилятором 1.4.

pitrik2

сорри
забыл поблагодарить
СПАСИБО!
есть же хорошие люди, которые не поленятся и дадут максимально исчерпывающий ответ

pitrik2

забыл сказать
выбрал первый вариант
так и буду впредь поступать
совместимости с 1.4 мне ен надо
скоро уже на шестерку переходить будем наверна
Оставить комментарий
Имя или ник:
Комментарий: