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

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

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

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

class User extends Entity {
}

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

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

Моя цель состоит в том, чтобы видеть "com.packagename. Пользователь" произвел к консоли, но вместо этого я собираюсь закончить с "com.packagename. На объект" начиная с класса Объекта ссылаются непосредственно от статического метода.

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

69
задан Matt Huggins 5 August 2010 в 18:25
поделиться

7 ответов

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

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

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

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

40
ответ дан 24 November 2019 в 13:46
поделиться

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

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
ответ дан 24 November 2019 в 13:46
поделиться

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

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

Вы могли:

  • Использовать существующий метод getClass ().
  • Передайте аргумент вашему статическому методу getClass () и вызовите метод экземпляра для этого объекта.
  • Сделайте ваш метод нестатическим и переименуйте его.
0
ответ дан 24 November 2019 в 13:46
поделиться

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

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

return this.getClass().getName();

Это вернет «Entity», если у вас есть экземпляр Entity , «User», если у вас есть User ] экземпляр и т. д.

89
ответ дан 24 November 2019 в 13:46
поделиться

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

System.out.println(User.class);

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

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

2
ответ дан 24 November 2019 в 13:46
поделиться

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

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

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

Это напечатает package.Entity и package.Derived как вам нужно. Беспорядочно, но послушайте, если это ваши ограничения ...

0
ответ дан 24 November 2019 в 13:46
поделиться

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

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 для выполнения операций. Скорее всего, он по-прежнему будет тесно связан с реализациями (как правило, это плохо, а если не плохо, то не особенно хорошо ), но я думаю, что такая структура лучше, чем суперкласс, выясняющий, что все из его подклассов.

3
ответ дан 24 November 2019 в 13:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: