2009-12-19 16 views
10

Est-il possible de retourner dans une méthode statique une classe? Je vais vous expliquer ...Java: classe de retour (pas une instance)

J'ai:

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

Je veux créer une méthode statique retourne sorcière B A. Ainsi, vous pouvez faire:

A.blah(); 

Et

B.getA().blah(); 

Ceci, sans créer une instance de A. Utilisez simplement les méthodes statiques.

Est-ce possible?

+1

soit lire http://gbracha.blogspot.com/2008/02/cutting-out-static.html ou apprendre C et utiliser des pointeurs de fonction. –

+0

Pas une réponse en tant que telle mais ... Scala utilise des objets singleton à la place des méthodes statiques (qui ne sont pas vraiment orientées objet). Si vous deviez utiliser Scala, vous pourriez très bien * faire * ce genre de chose. –

Répondre

7

C'est une réfutation de la réponse de @ irreputable:

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

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

elle « fonctionne », mais probablement pas dans le sens que vous attendez, et certainement pas d'une manière utile. Brisons ce en deux parties:

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

La première instruction renvoie une (null dans ce cas) instance de A, et la deuxième déclaration ne tient pas compte cette instance et l'appel A.blah(). Ainsi, ces déclarations sont en fait équivalent à

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

ou (étant donné que getA() est libre effet secondaire), tout simplement

A.blah(); 

Et voici un exemple qui illustre plus clairement:

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". 

... et ceci (j'espère) illustre pourquoi cette approche ne résout pas le problème du PO.

2

Non, cela est impossible. Vous pouvez uniquement renvoyer une référence à une instance d'une classe. Le plus proche que vous pouvez obtenir à ceci est de renvoyer une référence à une variable de type Class. La question est: pourquoi voulez-vous cela? Quel problème essayez-vous de résoudre? Il pourrait y avoir une meilleure solution.

2

Même s'il serait possible, il ne sera pas d'une grande utilité. L'appel A.blah() ne crée pas une instance de A. C'est une méthode statique sans besoin d'instance.

Et vous ne pouvez pas utiliser des interfaces pour mettre en œuvre des méthodes statiques. Alors, que devrait-il être bon?

6

Non, ce n'est pas possible. Vous avez deux options:

  1. B.getA() renvoie une instance de A, et blah() sera une méthode non statique.

  2. appeler directement A.blah().

+0

Possible, mais non recommandé. Voir cette réponse http://stackoverflow.com/questions/1932625/java-return-class-not-an-instance/1933573#1933573 –

+1

wow. C'est surprenant. – zedoo

1

Si vous ne voulez pas avoir une instance de A, puis laissez B appel blah() directement. C'est à dire.

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

Je vais deviner que la raison pour laquelle vous demandez ce que vous voulez est B pour revenir de nombreuses classes différentes avec des comportements différents - pas seulement A.

Vous voulez probablement utiliser une interface pour ce tu fais à la place.

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

Vous pouvez renvoyer une méthode en utilisant la réflexion que vous pouvez invoquer() plus tard. Cependant, il semble que vous essayez de faire quelque chose qui devrait être fait d'une autre manière. Pourquoi essayez-vous de faire cela?

4

Les gens disent qu'il est impossible, et c'est genre de vrai, mais si vous utilisez l'API de réflexion que vous pouvez faire quelque chose proche de cela.

Voici comment vous pouvez le faire.

Vous avez une classe qui fait cela.

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

puis d'appeler bla-vous:

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 
} 

Alors, pourquoi voudriez-vous faire? Eh bien, si vous le faites de cette façon, vous pouvez changer la classe A à So getA() pourrait renvoyer A, B, C ou D, tous avec différentes fonctions blah(). Je ne suis pas vraiment sûr de ce que cela servirait, mais si vous voulez le faire, vous pouvez le faire.

voir: Class.getDeclaredMethod() et Method.invoke() pour plus d'informations.

Je n'ai pas essayé cela, donc vous devrez peut-être faire quelques ajustements.

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

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

EDIT

Il est vrai qu'il est équivalent à

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

Sauf qu'ils regardent tout à fait différent. Imaginez que vous avez une chaîne de ceux-ci.

J'ai vérifié org.apache.commons.cli.OptionBuilder et personly je ne le ferais pas de cette façon, mais l'auteur a son cas. L'API est utilisée uniquement au début d'un programme, dans un seul thread.

Les concepteurs d'API doivent parfois faire des mouvements magiques, ne soyez pas trop critique.

+0

+1 pour avoir trouvé cette faille en Java.-1 pour ne pas avoir jeté un mot d'avertissement que cela ne devrait pas être fait. BTW, Eclipse génère cet avertissement lors de la compilation de ce code 'La méthode statique blah() du type A doit être accessible de manière statique'. –

+0

'org.apache.commons.cli.OptionBuilder' utilise cet anti-pattern d'appel de méthodes statiques sur les instances retournées. –

+0

Ce n'est pas une faille dans Java. C'est juste un exemple qui ne fait pas ce que vous pensez qu'il fait. Vois ma réponse. –