2009-12-19 26 views
10

¿Es posible devolver en un método estático una clase? Voy a explicar ...Java: Clase de devolución (No es una instancia)

que tengo:

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

que desea crear un método estático en la bruja B devuelve A. Por lo que puede hacer:

A.blah(); 

Y

B.getA().blah(); 

Esto, sin crear una instancia de A. Solo use sus métodos estáticos.

¿Esto es posible?

+1

o lea http://gbracha.blogspot.com/2008/02/cutting-out-static.html o conozca C y utilice los punteros a las funciones. –

+0

No es una respuesta como tal, pero ... Scala usa objetos únicos en lugar de métodos estáticos (que en realidad no están muy orientados a objetos). Si tuviera que usar Scala, entonces * podría * hacer * este tipo de cosas –

Respuesta

7

Esta es una refutación de la respuesta de @ irreputable:

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

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

"funciona", pero probablemente no en el sentido de que se puede esperar, y ciertamente no en una forma útil. Vamos a descomponerlo en dos partes:

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

La primera declaración está volviendo un (nula en este caso) instancia de A, y la segunda instrucción está ignorando esa instancia y llamando A.blah(). Por lo tanto, estas declaraciones son en realidad equivalente a

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

o (dado que getA() es libre de efectos secundarios), simplemente

A.blah(); 

Y he aquí un ejemplo que ilustra esto con mayor claridad:

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

... y esto (espero) ilustra por qué este enfoque no resuelve el problema del OP.

2

No, esto no es posible. Solo puede devolver una referencia a una instancia de una clase. Lo más cerca que puede llegar a esto es devolver una referencia a una variable de tipo Clase. La pregunta es: ¿por qué quieres esto? ¿Que problema estas tratando de resolver? Puede haber una mejor solución.

2

Incluso si fuera posible, no será de mucha utilidad. La llamada A.blah() no crea una instancia de A. Es un método estático sin necesidad de una instancia.

Y no puede usar interfaces para implementar métodos estáticos. Entonces, ¿para qué debería ser bueno?

6

No, esto no es posible. Tiene dos opciones:

  1. B.getA() devuelve una instancia de A y blah() habrá un método no estático.

  2. Llama directamente a A.blah().

+0

Posible, pero no recomendado. Vea esta respuesta http://stackoverflow.com/questions/1932625/java-return-class-not-an-instance/1933573#1933573 –

+1

wow. esto es sorprendente. – zedoo

1

Si no quiere tener una instancia de A, a continuación, dejar que B llamada blah() directamente. Es decir.

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

Voy a suponer que la razón por la que pregunte esto es que desea B para volver tantas clases diferentes, con diferentes comportamientos - no sólo A.

Es posible que desee utilizar una interfaz para lo lo estás haciendo en cambio.

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

Puede devolver una reflexión utilizando el método que se puede invocar() más tarde. Sin embargo, parece que estás tratando de hacer algo que debería hacerse de otra manera. ¿Por qué estás tratando de hacer esto?

4

La gente dice que es imposible, y eso es tipo de cierto, pero si utiliza la API de reflexión puede hacer algo parecido.

Así es como podría hacerlo.

Tienes una clase que hace esto.

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

entonces para llamar bla haces:

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 
} 

Así que, ¿por qué quieres hacer esto? Bueno, si lo haces de esta manera, puedes cambiar la clase A en So getA() podría devolver A, B, C o D, todos con diferentes funciones blah(). No estoy seguro de qué propósito serviría, pero si quieres hacerlo, puedes.

ver: Class.getDeclaredMethod() y Method.invoke() para obtener más información.

No he probado esto, por lo que es posible que deba hacer algunos ajustes.

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

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

EDITAR

Es cierto que es equivalente a

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

Salvo que se ven bastante diferente. Imagina que tienes una cadena de estos.

Revisé org.apache.commons.cli.OptionBuilder y personalmente no lo haría de esa manera, pero el autor tiene su caso. La API se usa solo al principio de un programa, en un solo hilo.

Los diseñadores de API a veces tienen que hacer algunos movimientos mágicos, no seas demasiado crítico.

+0

+1 para encontrar esta laguna en Java.-1 por no arrojar una advertencia de que esto no debería hacerse. Por cierto, Eclipse genera esta advertencia al compilar este código 'El método estático blah() del tipo A se debe acceder de una manera estática'. –

+0

'org.apache.commons.cli.OptionBuilder' utiliza este patrón anti de llamar a los métodos estáticos en las instancias devueltas. –

+0

Esto no es una laguna en Java. Es solo un ejemplo que no está haciendo lo que crees que está haciendo. Ver mi respuesta –

Cuestiones relacionadas