2011-02-08 36 views
21

Estaba jugando con la API de reflexión de Java y observé que los métodos con la lista de argumentos varicos se vuelven transitorios. ¿Por qué es eso y qué significa la palabra clave transient en este contexto?¿Por qué los métodos Java con varargs identificados como transitorios?

De Java Glosario, transitoria:

una palabra clave en el lenguaje de programación Java que indica que un campo no es parte de la forma de serie 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 sobre 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 
+2

¡Oh, interesante! Pensé que los métodos no se serializaron, así que ahora tengo curiosidad. – Kris

+0

Increíble hallazgo. :) – biziclop

+1

@biziclop qué es tan sorprendente, intente 'Modifier.toString (-1)', mucho mejor – bestsss

Respuesta

22

Una especie 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 dado que 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".

+2

Modifier.toString() toma una sola int y ... la toma desde allí; ya que no hay campo/método de diferencia, nunca puede ser correcto – bestsss

+0

@bestsss - eso es cierto. Pero se puede agregar otro método que también tome 'AccessibleObject' como argumento. O simplemente para agregar tanto el mensaje (ver mi actualización) – Bozho

+0

'AccessibleObject' no funcionará para Class, debe ser solo Object – bestsss

6

Esto parece un error en la implementación. Creo que la causa raíz podría ser que el bit configurado en el archivo .class para campos transitorios es el mismo para los métodos varargs (ver http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf, páginas 122 y 119).

+0

¿por qué error? puede pasar cualquier número arbitrario, y obtendrá algún resultado – bestsss

+0

@ bestsss- Ese es un buen punto. Tenía la impresión de que la clase 'Modificador' tenía más información acerca de dónde venían las banderas. – templatetypedef

+0

+1 para citar la fuente – Bozho

3

El indicador de un campo transitorio se ha sobrecargado en el contexto de un método para indicar que el método es un método vararg.

Del mismo modo, el indicador de un campo volátil se ha sobrecargado en el contexto de un método que significa que el método es un método de puente.

Ver: http://java.sun.com/docs/books/vmspec/2nd-edition/ClassFileFormat-Java5.pdf

páginas 118-122 (o 26-30 en el archivo PDF)

actualización

lectura del código fuente para Modifier.java confirma la primera frase de este respuesta ("La bandera de 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; 
+0

Esta respuesta es la más cercana a la respuesta correcta y debería ser la respuesta aceptada . El enlace a ClassFileFormat está roto. – Jason

Cuestiones relacionadas