Получение имени подкласса из суперкласса

Допустим, у меня есть базовый класс с именем Entity. В этом классе у меня есть статический метод для получения имени класса:

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

теперь у меня есть другой класс, расширяющий это.

class User extends Entity {
}

Я хочу получить имя класса пользователей:

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

моя цель-увидеть " com.имя_пакета.Пользователь "выводит на консоль, но вместо этого я собираюсь закончить" com.имя_пакета.Entity", поскольку на класс Entity ссылаются непосредственно из статического метод.

если бы это не был статический метод, это можно было бы легко решить с помощью this сайта в Entity класса (т. е.: return this.class.getClass()). Однако мне нужно, чтобы этот метод оставался статичным. Есть предложения, как к этому подойти?

12 ответов


не возможно. Статические методы никоим образом не являются полиморфными во время выполнения. Совершенно невозможно различить эти случаи:

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

они компилируются в один и тот же байтовый код (при условии, что метод определен в Entity).

кроме того, как бы вы назвали этот метод таким образом, чтобы он имел смысл быть полиморфным?


не делайте метод статическим. Проблема в том, что при вызове getClass() вы вызываете метод в супер классе - статические методы не наследуются. Кроме того, вы в основном имя-shadowing Object.getClass(), что сбивает с толку.

Если вам нужно зарегистрировать имя класса в суперклассе, используйте

return this.getClass().getName();

это вернет "сущность", когда у вас есть Entity экземпляра, "пользователь", когда у вас есть User экземпляров и т. д.


Ваш вопрос неоднозначен, но, насколько я могу сказать, вы хотите знать текущего класса из статического метода. Тот факт, что классы наследуют друг от друга, не имеет значения, но ради обсуждения я реализовал его таким образом.

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

это работает для меня

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

но я не уверен, как это работает.


суперкласс не должен даже знать о существовании подкласса, а тем более выполнять операции на основе полного имени подкласса. Если вам нужны операции, основанные на том, что такое точный класс, и вы не можете выполнить необходимую функцию по наследованию, вы должны сделать что-то в этом роде:

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;
    }
}

(непроверенного кода)

этот класс также не знает о своих подклассах, а скорее использует Class класс для выполнения операций. Скорее всего, он все равно будет тесно связан с реализациями (как правило, плохо, или, если не плохо, это не особенно хороший), но я думаю, что такая структура лучше, чем суперкласс выяснить, что все его подклассы.


почему вы хотите реализовать свой собственный метод getClass ()? Вы можете просто использовать

System.out.println(User.class);

редактировать (немного подробнее): вы хотите, чтобы метод был статическим. В этом случае вы должны вызвать метод для класса, имя которого вы хотите, будь то подкласс или суперкласс. Тогда вместо вызова MyClass.getClass(), вы можете просто позвонить MyClass.class или MyClass.class.getName().

кроме того, вы создаете static метод с той же сигнатурой, что и Object.getClass() метод экземпляра , который не будет компилироваться.


  1. создайте строковую переменную-член в суперклассе.
  2. добавить этого.getClass().getName () конструктору, который хранит значение в строковой переменной-члене.
  3. создайте геттер для возврата имени.

каждый раз, когда экземпляр расширенного класса создается, его имя будет храниться в строке и доступно с геттером.


статический метод связан с классом, а не с конкретным объектом.

рассмотрим, как это будет работать, если существует несколько подклассов - например, администратор также является сущностью. Как бы ваш статический метод сущности, связанный только с классом сущности, знал, какой подкласс вы хотите?

вы можете:

  • используйте существующий метод getClass ().
  • передайте аргумент вашему статическому методу getClass () и вызовите метод экземпляра на этом объекте.
  • сделайте свой метод нестатическим и переименуйте его.

Если я правильно понимаю ваш вопрос, я думаю, что единственный способ достичь того, что вы хотите,-это повторно реализовать статический метод в каждом подклассе, например:

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

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

Это будет печатать пакет.Сущность и пакет.Производный как вы требуете. Грязно, но эй, если это ваши ограничения...


Если я правильно понял, вы хотите использовать свой подкласс в базовом классе в статическом методе Я думаю, вы можете сделать это, передав параметр класса методу

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

мой контекст: сущность суперкласса с подклассами для объектов XML. Мое решение: Создайте переменную класса в суперклассе

Class<?> claz;

тогда в подклассе я бы установил переменную суперкласса в конструкторе

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

Это очень просто сделать

пользователей.getClass().getSuperclass()