Получение имени подкласса из суперкласса
Допустим, у меня есть базовый класс с именем 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(); } }
суперкласс не должен даже знать о существовании подкласса, а тем более выполнять операции на основе полного имени подкласса. Если вам нужны операции, основанные на том, что такое точный класс, и вы не можете выполнить необходимую функцию по наследованию, вы должны сделать что-то в этом роде:
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()
метод экземпляра , который не будет компилироваться.
- создайте строковую переменную-член в суперклассе.
- добавить этого.getClass().getName () конструктору, который хранит значение в строковой переменной-члене.
- создайте геттер для возврата имени.
каждый раз, когда экземпляр расширенного класса создается, его имя будет храниться в строке и доступно с геттером.
статический метод связан с классом, а не с конкретным объектом.
рассмотрим, как это будет работать, если существует несколько подклассов - например, администратор также является сущностью. Как бы ваш статический метод сущности, связанный только с классом сущности, знал, какой подкласс вы хотите?
вы можете:
- используйте существующий метод 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();
}
}