que - ¿Por qué los métodos de Java con varargs identificados como transitorios?
varargs java (3)
Estaba jugando con Java Reflection API y observé que los métodos con la lista de argumentos variadic se vuelven transitorios. ¿Por qué es eso y qué significa transient
palabra clave transient
en este contexto?
Desde Java Glosario, transitorio :
Una palabra clave en el lenguaje de programación Java que indica que un campo no es parte de la forma serializada de un objeto. Cuando un objeto se serializa, los valores de sus campos transitorios no se incluyen en la representación en serie, mientras que los valores de sus campos no transitorios se incluyen.
Sin embargo, esta definición no dice nada acerca de los métodos. ¿Algunas ideas?
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){}
}
Salidas:
main --> public static
foo --> public static transient
El tipo de respuesta se puede encontrar en el código de javassist AccessFlag
public static final int TRANSIENT = 0x0080;
public static final int VARARGS = 0x0080;
Parece que ambos tienen los mismos valores. Y como transient
no significa nada para los métodos, mientras que varargs no significa nada para los campos, está bien que sean iguales.
Pero no está bien que la clase Modifier
no tenga esto en cuenta. Me gustaría presentar un problema al respecto. Necesita una nueva constante - VARARGS
y un nuevo método - isVarargs(..)
. Y el método toString()
se puede reescribir para incluir "transient / varargs".
Esto parece un error en la implementación. Creo que la causa raíz podría ser que el bit establecido en el archivo .class para los campos transitorios es el mismo para los métodos varargs (consulte http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf , páginas 122 y 119).
La bandera para un campo transitorio se ha sobrecargado en el contexto de un método para significar que el método es un método vararg.
Del mismo modo, la bandera para un campo volátil se ha sobrecargado en el contexto de un método para indicar que el método es un método puente.
Consulte: http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf
páginas 118-122 (o 26-30 en el archivo PDF)
Actualizar
La lectura del código fuente de Modifier.java confirma la primera oración de esta respuesta ("La bandera para un campo transitorio se ha sobrecargado"). Aquí está el código fuente relevante:
// 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;