2016-04-18 13 views
8

Lo so, c'è già almeno one question on this topic. Ma voglio chiedere ancora una volta perché questo è quello che ho scoperto nel javadoc of Class#getDeclaredMethod(...):Più di un metodo con gli stessi tipi di parametro in una classe

Se più di un metodo con gli stessi tipi di parametri viene dichiarato in una classe , e uno di questi metodi ha un tipo di ritorno che è più specifico di tutti gli altri, tale metodo viene restituito; altrimenti uno dei metodi è scelto arbitrariamente.

Quindi gli sviluppatori della riflessione in Java considerano questo caso come probabile, è forse possibile dopotutto fare una tale dichiarazione? O forse è solo deprecato?

+0

probabilmente un metodo privato da una classe genitore che corrisponde a un metodo figlio? – flakes

+2

@flkes No, poiché 'getDeclaredMethods' trova solo metodi dichiarati sulla classe. Dovresti sempre trovare il metodo dichiarato sul bambino. – Radiodef

risposta

9

Il formato bytecode JVM consente la dichiarazione di più metodi con lo stesso nome e gli stessi tipi di parametri purché il tipo restituito sia diverso, sebbene Java linguaggio non lo consenta.. Ciò significa che a) altre lingue JVM possono farne uso eb) può essere utilizzato per speciali caratteristiche del linguaggio "compiler-magic".

Più comunemente, il compilatore emette più metodi con lo stesso nome e gli stessi tipi di parametri quando si tratta di generici. La ricerca del metodo JVM si basa sull'intera firma per corrispondere, non solo sui tipi di parametri. Pertanto, il compilatore deve emettere i cosiddetti metodi bridge che sovrascrivono o ombreggiano altri metodi in base alla firma. Considerate questo esempio:

interface Foo<T> 
{ 
    T foo(); // desc:()Ljava/lang/Object; 

    void bar(T value); // desc: (Ljava/lang/Object;)V 

    Object baz(); // desc:()Ljava/lang/Object; 
} 

class StringFoo implements Foo<String> 
{ 
    @Override 
    public String foo() { ... } // desc:()Ljava/lang/String; // ! 

    @Override 
    public void bar(String value) { ... } // desc: (Ljava/lang/String;)V // ! 

    @Override 
    public String baz() { ... } // desc:()Ljava/lang/String; // ! 
} 

La classe StringFoo bisogno di tre metodi bridge aggiuntivi per sovrascrivere effettivamente i metodi di interfaccia in termini di avere lo stesso desc:

class StringFoo implements Foo<String> 
{ 
    public String foo() { ... } 

    public /* synthetic bridge */ Object foo() // desc:()Ljava/lang/Object; 
    { 
     return /* String */ foo(); // statically linked to String foo() 
    } 

    public void bar(String value) { ... } 

    public /* synthetic bridge */ void bar(Object value) // desc: (Ljava/lang/Object;) 
    { 
     return bar((String) value); 
    } 

    public String baz() { ... } 

    public /* synthetic bridge */ Object baz() // desc:()Ljava/lang/Object; 
    { 
     return /* String */ baz(); // statically linked to String baz() 
    } 
} 

Le pseudo-modificatori synthetic bridge sono due accessi JVM contrassegni utilizzati solo dal compilatore per contrassegnare i metodi generati automaticamente nel bytecode

La metrica Class#getDeclaredMethods od restituisce tutti i metodi dichiarati - inclusi i metodi di bridge sintetici. Pertanto, #getDeclaredMethod(String) deve sceglierne uno che è l'implementazione effettiva.

+0

Puoi spiegare o fornire un link a cosa sia un "ponte sintetico"? – flakes

+0

@flkes modificato. Questi pseudo-modificatori non sono particolarmente importanti per l'utente, il compilatore li usa solo per contrassegnare metodi speciali. – Clashsoft