2010-08-05 11 views
54

Digamos que tengo una clase base llamada Entity. En esa clase, tengo un método estático para recuperar el nombre de clase:Obteniendo el nombre de una subclase dentro de una superclase

class Entity { 
    public static String getClass() { 
     return Entity.class.getClass(); 
    } 
} 

Ahora tengo otra clase extender eso.

class User extends Entity { 
} 

que desea obtener el nombre de la clase de usuario:

System.out.println(User.getClass()); 

Mi objetivo es ver la salida "com.packagename.User" a la consola, sino que voy a terminar con "com.packagename.Entity" ya que la clase Entity se referencia directamente desde el método estático.

Si no se trata de un método estático, esto podría resolverse fácilmente utilizando la palabra clave this dentro de la clase Entity (es decir, return this.class.getClass()). Sin embargo, necesito este método para permanecer estático. ¿Alguna sugerencia sobre cómo abordar esto?

Respuesta

36

No es posible. Los métodos estáticos no son polimórficos en tiempo de ejecución de ninguna manera. Es absolutamente imposible distinguir estos casos:

System.out.println(Entity.getClass()); 
System.out.println(User.getClass()); 

Recopilan con el mismo código de bytes (suponiendo que el método está definido en Entity).

Además, ¿cómo llamarías a este método de una manera en la que tendría sentido que fuera polimórfico?

+1

Gracias por aclarar, supongo que no sé lo suficiente acerca de cómo se compilan los métodos estáticos. Esto ayuda a aclarar las cosas, tendré que trabajar en una solución alternativa. –

+2

+1, exactamente a la derecha. Toda esta pregunta nace de un malentendido sobre cómo funcionan los métodos estáticos. –

2

¿Por qué quiere implementar su propio método getClass()? Usted sólo puede usar

System.out.println(User.class); 

Editar (para elaborar un poco): Usted quiere que el método sea estática. En ese caso, debe llamar al método en la clase cuyo nombre de clase desea, ya sea la subclase o la superclase. Luego, en lugar de llamar al MyClass.getClass(), puede simplemente llamar al MyClass.class o al MyClass.class.getName().

Además, está creando un método static con la misma firma que el método de instancia Object.getClass(), que no se compilará.

+1

Intencionalmente escribí la pregunta por lo que sería muy básico en StackOverflow y llegaría directamente al punto de la pregunta. Es realmente porque estoy construyendo un método estático mucho más robusto que utiliza el nombre de la clase de cualquier subclase que amplíe esta clase base abstracta. –

+1

Parece que quieres polimorfismo a través de métodos "estáticos", lo cual no es posible. Además, ¿puede explicar por qué lo anterior no es lo suficientemente robusto? – samitgaur

+0

No es lo suficientemente robusto porque tendré que redefinir el método estático en cada clase de herencia en lugar de solo poder definir el método estático una vez. –

67

No haga que el método sea estático. El problema es que al invocar getClass() está llamando al método en la superclase: los métodos estáticos no se heredan. Además, básicamente estás ocultando nombres Object.getClass(), lo cual es confuso.

Si tienes que entrar el nombre de clase dentro de la superclase, utilice

return this.getClass().getName(); 

Esto devolverá "Entidad" cuando tiene una Entity ejemplo, "Usuario" cuando se tiene un ejemplo User, etc.

+1

'this' no existe en un método estático. –

+24

@Matt Huggins, es por eso que la primera oración en mi respuesta dice 'No hagas que el método sea estático' –

+2

@ matt b - es por eso que la penúltima oración de mi pregunta dice' Sin embargo, necesito este método para permanecer static. –

0

Un método estático está asociado con una clase, no con un objeto específico.

Considere cómo funcionaría esto si hubiera múltiples subclases; por ejemplo, el Administrador también es una Entidad. ¿Cómo sabría su método de Entidad estática, asociado solo con la clase Entidad, qué subclase quería?

Usted podría:

  • Uso método de los getClass existentes().
  • Pase un argumento a su método estático getClass(), y llame a un método de instancia en ese objeto.
  • Haga que su método no sea estático y cambie el nombre.
0

Si entiendo bien su pregunta, creo que la única manera de lograr lo que desea es volver a poner en práctica el método estático en cada subclase, por ejemplo:

class Entity { 
    public static String getMyClass() { 
     return Entity.class.getName(); 
    } 
} 

class Derived extends Entity { 
    public static String getMyClass() { 
     return Derived.class.getName(); 
    } 
} 

Esto imprimirá paquete .Edad y paquete. Derivado como lo requiera. Desordenado pero bueno, si esas son tus limitaciones ...

6

Tu pregunta es ambigua pero, por lo que puedo decir, quieres saber la clase actual desde un método estático. El hecho de que las clases se hereden entre sí es irrelevante, pero por el bien de la discusión lo implementé de esta manera también.

 
class Parent { 
    public static void printClass() { 
     System.out.println(Thread.currentThread().getStackTrace()[2].getClassName()); 
    } 
} 

public class Test extends Parent { 
    public static void main(String[] args) { 
     printClass(); 
    } 
} 
+0

Ouch, que * stacktrace-hack * está sucio. ¿Qué pasa con 'System.out.println (Parent.class.getName());'? – whiskeysierra

+2

Como dije, la pregunta de Matt es ambigua y proporcioné una de las respuestas posibles. Es evidente que su versión no da el mismo resultado que mi código, por lo que no hay comparación, está hablando de una solución diferente. Y leer la pila de subprocesos no es un truco, es una forma normal de verificar la jerarquía de llamadas (por supuesto me salté la verificación de cordura ya que este es un ejemplo). – Gilead

+0

Este es un hack bastante divertido, pero tiene poco que ver con el comportamiento solicitado. Esta función imprime el nombre de la clase * llamando * al método (es decir, si quita 'extends Parent' y cambia la llamada a' Parent.printClass() ', sigue imprimiendo" Test "). – nemetroid

3

La superclase no debería siquiera saben de la existencia de la subclase, y mucho menos realizar operaciones basadas en el nombre completo de la subclase. Si necesita operaciones sobre la base de lo que la clase exacta es, y no puede realizar la función necesaria por herencia, que debe hacer algo en este sentido:

public class MyClassUtil 
{ 
    public static String doWorkBasedOnClass(Class<?> clazz) 
    { 
     if(clazz == MyNormalClass.class) 
     { 
      // Stuff with MyNormalClass 
      // Will not work for subclasses of MyNormalClass 
     } 

     if(isSubclassOf(clazz, MyNormalSuperclass.class)) 
     { 
      // Stuff with MyNormalSuperclass or any subclasses 
     } 

     // Similar code for interface implementations 
    } 

    private static boolean isSubclassOf(Class<?> subclass, Class<?> superclass) 
    { 
     if(subclass == superclass || superclass == Object.class) return true; 

     while(subclass != superclass && subclass != Object.class) 
     { 
      subclass = subclass.getSuperclass(); 
     } 
     return false; 
    } 
} 

(código no probado)

Esta clase doesn Tampoco conoce sus propias subclases, sino que usa la clase Class para realizar operaciones. Lo más probable es que todavía esté estrechamente relacionado con las implementaciones (generalmente algo malo, o si no está mal, no es especialmente bueno), pero creo que una estructura como esta es mejor que una superclase averiguando cuáles son todas sus subclases. .

-4

Es muy simple hecho por

User.getClass(). GetSuperclass()

+2

Esto hace lo contrario de lo que se preguntaba. Quería el nombre de una subclase dentro de una superclase. Su respuesta proporciona el nombre de la superclase dentro de una subclase. –

2
  1. Crear una variable String miembro de la superclase.
  2. Agregue this.getClass(). GetName() a un constructor que almacena el valor en la variable de cadena miembro.
  3. Crea un getter para devolver el nombre.

Cada vez que se crea una instancia de la clase extendida, su nombre se almacenará en la Cadena y se podrá acceder con el captador.

0

si estoy tomando las cosas bien que desea utilizar su subclase en la clase base en el método estático Creo que se puede hacer esto pasando un parámetro de clase con el método

class Entity { 
    public static void useClass(Class c) { 
     System.out.println(c); 
     // to do code here 
    } 
} 

class User extends Entity { 
} 

class main{ 
    public static void main(String[] args){ 
     Entity.useClass(Entity.class); 
    } 
} 
0

mi contexto: Entidad superclase con subclases para objetos XML. Mi solución: Crear una variable de clase en la superclase

Class<?> claz; 

Luego, en la subclase Me gustaría establecer la variable de la superclase en el constructor

public class SubClass { 
    public SubClass() { 
    claz = this.getClass(); 
    } 
} 
3

Esto funciona para mí

this.getClass().asSubclass(this.getClass()) 

Pero no estoy seguro de cómo funciona.

Cuestiones relacionadas