Obtener el nombre de una subclase desde una superclase


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

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

Ahora tengo otra clase extender eso.

class User extends Entity {
}

Quiero obtener el nombre de la clase del Usuario:

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

Mi objetivo es ver com.packagename.Usuario "salida a la consola, pero en su lugar voy a terminar con" com.packagename.Entity " ya que la clase Entity está siendo referenciada directamente desde el método estático.

Si esto no fuera un método estático, esto se podría resolver fácilmente usando la palabra clave this dentro de la clase Entity (es decir: return this.class.getClass()). Sin embargo, necesito que este método permanezca estático. Alguna sugerencia sobre cómo abordar esto?

Author: Matt Huggins, 2010-08-05

12 answers

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());

Se compilan con el mismo código de bytes (asumiendo 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?

 38
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-05 19:18:33

No haga que el método sea estático. El problema es que cuando invoca getClass() está llamando al método en la clase super - los métodos estáticos no se heredan. Además, básicamente estás sombreando nombres Object.getClass(), lo cual es confuso.

Si necesita registrar el nombre de la clase dentro de la superclase, use

return this.getClass().getName();

Esto devolverá "Entidad" cuando tenga una instancia Entity, "Usuario" cuando tenga una instancia User, etc.

 72
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-05 18:36:54

Su pregunta es ambigua, pero por lo que puedo decir, desea conocer la clase actual de un método estático. El hecho de que las clases hereden unas de otras 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();
    }
}
 6
Author: Gilead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-05 18:44:43

Esto funciona para mí

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

Pero no estoy seguro de cómo funciona.

 5
Author: sirolf2009,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:00:47

La superclase ni siquiera debe saber de la existencia de la subclase, mucho menos realizar operaciones basadas en el nombre completo de la subclase. Si necesita operaciones basadas en cuál es la clase exacta, y no puede realizar la función necesaria por herencia, 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 tampoco conoce sus propias subclases, sino que utiliza la clase Class para realizar operaciones. Lo más probable es que todavía estar estrechamente vinculado con las implementaciones (generalmente una cosa mala, o si no es malo no es especialmente bueno), pero creo que una estructura como esta es mejor que una superclase averiguar lo que todas sus subclases son.

 3
Author: Brian S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-07 10:03:20

¿Por qué quieres implementar tu propio método getClass ()? Solo puede usar

System.out.println(User.class);

Edit (para elaborar un poco): Desea que el método sea estático. 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 a MyClass.getClass(), solo puede llamar a MyClass.class o 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á.

 2
Author: samitgaur,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-06 04:15:17
  1. Cree una variable de cadena miembro en la superclase.
  2. Añadir el esto.getClass().getName () a un constructor que almacena el valor en la variable de cadena miembro.
  3. Cree un getter para devolver el nombre.

Cada vez que se instancie la clase extendida, su nombre será almacenado en la Cadena y accesible con el getter.

 2
Author: Dawg 'N IT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-13 03:37:32

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

Considere cómo funcionaría esto si hubiera varias subclases e 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 de Entidad, qué subclase quería?

Usted podría:

  • Use el método getClass() existente.
  • Pasa un argumento a tu método getClass() estático y llama a un método de instancia en ese objeto.
  • Make su método no estático, y cambiarle el nombre.
 0
Author: Andy Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-05 18:38:00

Si entiendo su pregunta correctamente, creo que la única manera de lograr lo que desea es volver a implementar 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á el paquete.Entidad y paquete.Derivado como usted requiere. Desordenado pero bueno, si esas son tus limitaciones...

 0
Author: brabster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-05 18:46:00

Si lo estoy tomando bien, desea usar su subclase en la clase base en el método estático Creo que puedes hacer esto pasando un parámetro de clase al 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
Author: Dis Honest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-18 06:02:33

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

Class<?> claz;

Entonces en la subclase establecería la variable de la superclase en el constructor

public class SubClass {
   public SubClass() {
     claz = this.getClass();
   }
}
 0
Author: Matthias dirickx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-26 10:19:54

Es muy simple hecho por

Usuario.getClass().getSuperclass ()

 -4
Author: NightGale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-10 00:11:25