2011-02-08 12 views
21

Stavo giocando con Java Reflection API e ho osservato che i metodi con lista di argomenti variadici diventano transitori. Perché questo e cosa significa la parola chiave transient in questo contesto?Perché i metodi Java con vararg identificati come transitori?

Da Java Glossario, transitoria:

Una parola chiave nel linguaggio di programmazione Java che indica che un campo non è parte della forma serializzata di un oggetto. Quando un oggetto viene serializzato, i valori dei suoi campi transitori non sono inclusi nella rappresentazione seriale, mentre i valori dei suoi campi non transitori sono inclusi.

Tuttavia questa definizione non dice nulla sui metodi. Qualche idea?

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){} 
} 

Uscite:

main --> public static 
foo --> public static transient 
+2

Oh, interessante! Avevo pensato che i metodi non diventassero serializzati quindi ora sono curioso. – Kris

+0

Incredibile scoperta. :) – biziclop

+1

@biziclop cosa c'è di così sorprendente, prova 'Modifier.toString (-1)', molto meglio – bestsss

risposta

22

Una specie di risposta può essere trovata nel codice di javassist AccessFlag

public static final int TRANSIENT = 0x0080; 
public static final int VARARGS = 0x0080; 

Sembra entrambi hanno gli stessi valori. E dal momento che transient non significa nulla per i metodi, mentre varargs non significa nulla per i campi, va bene che siano uguali.

Ma non è corretto per la classe Modifier non tenerne conto. Presenterei un problema al riguardo. Ha bisogno di una nuova costante - VARARGS e un nuovo metodo - isVarargs(..). E il metodo toString() può essere riscritto per includere "transient/varargs".

+2

il Modifier.toString() prende un singolo int e .. lo prende da lì; poiché non esiste un campo/metodo diverso, non può mai essere corretto – bestsss

+0

@bestsss: è vero. Ma si può aggiungere un altro metodo che accetta 'AccessibleObject' come argomento. O semplicemente per aggiungere sia il messaggio (vedi il mio aggiornamento) – Bozho

+0

'AccessibleObject' non funzionerà per la classe, deve essere solo l'oggetto – bestsss

6

Questo appare come un bug nell'implementazione. Penso che la causa principale potrebbe essere che il bit impostato nel file .class per i campi transitori è lo stesso per i metodi varargs (vedere http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf, pagine 122 e 119).

+0

perché bug? puoi passare qualsiasi numero arbitrario e otterrai dei risultati – bestsss

+0

@ bestsss- Questo è un buon punto. Avevo l'impressione che la classe 'Modifier' avesse più informazioni su dove venissero le bandiere. – templatetypedef

+0

+1 per la citazione della fonte – Bozho

3

Il flag per un campo transitorio è stato sovraccaricato nel contesto di un metodo per indicare che il metodo è un metodo vararg.

Allo stesso modo, il flag per un campo volatile è stato sovraccaricato nel contesto di un metodo per indicare che il metodo è un metodo bridge.

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

pagine 118-122 (o 26-30 nel file PDF)

Aggiornamento

Leggendo il codice sorgente per Modifier.java conferma la prima frase del presente answer ("Il flag per un campo transitorio è stato sovraccaricato"). Ecco il codice sorgente pertinente:

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

Questa risposta è la più vicina alla risposta corretta e dovrebbe essere la risposta accettata . Il collegamento a ClassFileFormat è danneggiato. – Jason

Problemi correlati