2009-12-19 6 views
10

È possibile restituire un metodo statico a una classe? Spiegherò ...Java: Classe di ritorno (non un'istanza)

ho:

public class A { public static void blah(){} } 
public class B { } 

Voglio creare un metodo statico in strega B restituisce A. Così si può fare:

A.blah(); 

E

B.getA().blah(); 

Questo, senza creare un'istanza di A. Basta usare metodi statici.

È possibile?

+1

o leggi http://gbracha.blogspot.com/2008/02/cutting-out-static.html o impara C e usa i puntatori di funzione. –

+0

Non è una risposta in quanto tale ma ... Scala usa oggetti singleton al posto di metodi statici (che in realtà non sono molto orientati agli oggetti). Se dovessi usare Scala, allora * potresti * fare questo genere di cose –

risposta

7

Questa è una confutazione di @ di irreputable risposta:

public class B { 
    public static A getA(){ return null; } 
} 

B.getA().blah(); //works! 

"funziona", ma probabilmente non nel senso che ci si aspetta, e certamente non in modo utile. Facciamo una scomposizione in due parti:

A a = B.getA(); 
a.blah(); 

La prima istruzione restituisce un (null in questo caso) istanza di A, e la seconda istruzione sta ignorando tale istanza e chiamando A.blah(). Quindi, queste affermazioni sono in realtà equivale a

B.getA(); 
A.blah(); 

o (visto che getA() è effetto collaterale gratuito), semplicemente

A.blah(); 

Ed ecco un esempio che illustra questo più chiaramente:

public class A { 
    public static void blah() { System.err.println("I'm an A"); } 
} 

public class SubA extends A { 
    public static void blah() { System.err.println("I'm a SubA"); } 
} 

public class B { 
    public static A getA(){ return new SubA(); } 
} 

B.getA().blah(); //prints "I'm an A". 

... e questo (spero) illustra perché questo approccio non risolve il problema dell'OP.

2

No, questo non è possibile. Puoi solo restituire un riferimento a un'istanza di una classe. Il più vicino che puoi ottenere è di restituire un riferimento a una variabile di tipo Class. La domanda è: perché lo vuoi? Che problema stai cercando di risolvere? Potrebbe esserci una soluzione migliore.

2

Anche se sarebbe possibile, non sarà molto utile. La chiamata A.blah() non crea un'istanza di A. È un metodo statico senza necessità di un'istanza.

E non è possibile utilizzare le interfacce per implementare metodi statici. Quindi cosa dovrebbe essere buono per?

6

No, questo non è possibile. Sono disponibili due opzioni:

  1. B.getA() restituisce un'istanza di A, e blah() sarà un metodo non statico .

  2. Chiamare direttamente A.blah().

+0

Possibile, ma non raccomandato. Vedi questa risposta http://stackoverflow.com/questions/1932625/java-return-class-not-an-instance/1933573#1933573 –

+1

wow. questo è sorprendente .. – zedoo

1

Se non si vuole avere un'istanza di A, allora lasciate B chiamata blah() direttamente. Cioè

class B { 
    void blah() { 
     A.blah(); 
    } 
} 
6

ho intenzione di indovinare che la ragione, vi faccio questa è che si desidera B per tornare molte classi differenti con differenti comportamenti - non solo A.

Probabilmente si desidera utilizzare un'interfaccia per quello stai invece facendo.

interface IA { 
    void blah(); 
} 

public class B { 
    IA getA1() { 
    return new IA { 
     void blah() { 
      ...code... 
     } 
    } 
    } 
    IA getA2() { 
    ... 
    } 
    IA getA3() { 
    ... 
    } 
} 

myCallingMethod { 
    B.getA1().blah(); 
    B.getA2().blah(); 
    B.getA3().blah(); 
} 
0

È possibile restituire un metodo utilizzando il riflesso che è possibile richiamare() in seguito. Tuttavia, sembra che tu stia cercando di fare qualcosa che dovrebbe essere fatto in un altro modo. Perché stai provando a fare questo?

4

Le persone dicono che è impossibile, e questo è tipo di true, ma se si utilizza l'API di riflessione è possibile fare qualcosa di simile.

Ecco come si potrebbe fare.

Hai una classe che fa questo.

public class B { 
    Class a 
    public static Class getA(){ 
     return a; 
    } 
} 

poi per chiamare bla fare:

try{ 
    Method m = B.getA().getDeclaredMethod("blah"); 
    m.invoke(null);//for a static method, you can invoke on null 
} 
Catch(Exception e){ 
    // see documentation for list of exceptions 
} 

Allora, perché si vuole fare questo? Bene, se lo fai in questo modo puoi cambiare la classe A a So getA() potrebbe restituire A, B, C o D, il tutto con diverse funzioni blah(). Non sono veramente sicuro di quale scopo servirebbe, ma se vuoi farlo, puoi farlo.

vedere: Class.getDeclaredMethod() e Method.invoke() per ulteriori informazioni.

Non ho provato questo, quindi potrebbe essere necessario apportare qualche ritocco.

1
public class B { 
    public static A getA(){ return null; } 
} 

B.getA().blah(); //works! 

EDIT

E 'vero che è equivalente a

B.getA(); 
A.blah(); 

Solo che guardano molto diverso. Immagina di avere una catena di questi.

Ho controllato org.apache.commons.cli.OptionBuilder e personalmente non lo farei in questo modo, ma l'autore ha il suo caso. L'API viene utilizzata solo all'inizio di un programma, in un singolo thread.

I progettisti di API a volte devono fare alcune mosse magiche, non giudicare troppo.

+0

+1 per aver trovato questa scappatoia in Java.-1 per non lanciare una parola di avvertimento che questo non dovrebbe essere fatto. BTW, Eclipse genera questo avvertimento durante la compilazione di questo codice 'Il metodo statico blah() dal tipo A dovrebbe essere accessibile in modo statico'. –

+0

'org.apache.commons.cli.OptionBuilder' utilizza questo anti-pattern per chiamare i metodi statici sulle istanze restituite. –

+0

Questa non è una scappatoia in Java. È solo un esempio che non sta facendo quello che pensi che stia facendo. Vedi la mia risposta. –

Problemi correlati