Почему Java-методы с varargs определены как переходные?
Я играл с API Java Reflection и наблюдал, что методы с вариационным списком аргументов становятся временными. Почему это и что означает ключевое слово transient
в этом контексте?
Из Java Glossary, переходный:
Ключевое слово на языке программирования Java, которое указывает, что поле не является частью сериализованной формы объекта. Когда объект сериализуется, значения его переходных полей не включаются в последовательное представление, тогда как значения его непереходных полей включены.
Однако это определение ничего не говорит о методах. Любые идеи?
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Dummy {
public static void main(String[] args) {
for(Method m : Dummy.class.getDeclaredMethods()){
System.out.println(m.getName() + " --> "+Modifier.toString(m.getModifiers()));
}
}
public static void foo(int... args){}
}
Выходы:
main --> public static
foo --> public static transient
Ответы
Ответ 1
Отклик ответа можно найти в коде javassist AccessFlag
public static final int TRANSIENT = 0x0080;
public static final int VARARGS = 0x0080;
Кажется, оба имеют одинаковые значения. А так как transient
ничего не значит для методов, в то время как varargs ничего не значит для полей, для них нормально быть одинаковыми.
Но это не нормально для класса Modifier
, чтобы не учитывать это. Я бы опубликовал вопрос об этом. Ему нужна новая константа - VARARGS
и новый метод - isVarargs(..)
. И метод toString()
можно переписать, чтобы включить "переходные/varargs".
Ответ 2
Это выглядит как ошибка в реализации. Я думаю, что основной причиной может быть то, что бит, установленный в .class файле для переходных полей, одинаковый для методов varargs (см. http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf, стр. 122 и 119).
Ответ 3
Флаг для переходного поля был перегружен в контексте метода, чтобы означать, что метод является методом vararg.
Аналогично, флаг для изменчивого поля был перегружен в контексте метода, чтобы означать, что метод является мостиковым методом.
Смотрите: http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf
страницы 118-122 (или 26-30 в файле PDF)
Update
Чтение исходного кода для Modifier.java подтверждает первое предложение этого ответа ( "Флаг для временного поля перегружен" ). Вот соответствующий исходный код:
// Bits not (yet) exposed in the public API either because they
// have different meanings for fields and methods and there is no
// way to distinguish between the two in this class, or because
// they are not Java programming language keywords
static final int BRIDGE = 0x00000040;
static final int VARARGS = 0x00000080;
static final int SYNTHETIC = 0x00001000;
static final int ANNOTATION = 0x00002000;
static final int ENUM = 0x00004000;
static final int MANDATED = 0x00008000;