Получение имени подкласса из суперкласса
Скажем, у меня есть базовый класс с именем Entity
. В этом классе у меня есть статический метод для получения имени класса:
class Entity {
public static String getClass() {
return Entity.class.getClass();
}
}
Теперь у меня есть еще один класс.
class User extends Entity {
}
Я хочу получить имя класса пользователя:
System.out.println(User.getClass());
Моя цель - увидеть вывод "com.packagename.User" на консоль, но вместо этого я вернусь к "com.packagename.Entity", поскольку на класс Entity ссылаются непосредственно из статического метода.
Если это не был статический метод, это можно было легко решить, используя ключевое слово this
в классе Entity
(т.е. return this.class.getClass()
). Однако мне нужно, чтобы этот метод оставался статичным. Любые предложения о том, как подойти к этому?
Ответы
Ответ 1
Невозможно. Статические методы не являются полиморфными во время выполнения. Совершенно невозможно отличить эти случаи:
System.out.println(Entity.getClass());
System.out.println(User.getClass());
Они скомпилируются с одним и тем же байтовым кодом (предполагается, что метод определен в Entity
).
Кроме того, как бы вы назвали этот метод таким образом, чтобы иметь смысл полиморфно?
Ответ 2
Не ставьте метод статическим. Проблема в том, что при вызове getClass()
вы вызываете метод в суперклассе - статические методы не наследуются. Кроме того, вы в основном затеняете имя Object.getClass()
, что сбивает с толку.
Если вам нужно записать имя класса в суперкласс, используйте
return this.getClass().getName();
Это приведет к возврату "Entity", если у вас есть экземпляр Entity
, "Пользователь", когда у вас есть экземпляр User
и т.д.
Ответ 3
Ваш вопрос неоднозначен, но насколько я могу судить, вы хотите узнать текущий класс из статического метода. Тот факт, что классы наследуются друг от друга, не имеет значения, но для обсуждения я также реализовал его таким образом.
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();
}
}
Ответ 4
Суперкласс не должен даже знать о существовании подкласса, а тем более выполнять операции на основе полного имени подкласса. Если вам нужны операции, основанные на том, что такое точный класс, и не может выполнить необходимую функцию по наследованию, вы должны сделать что-то в этом направлении:
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
для выполнения операций. Скорее всего, он все равно будет тесно связан с реализациями (как правило, это плохо, или, если не плохо, это не особенно хорошо), но я думаю, что такая структура лучше, чем суперкласс, выясняя, что все его подклассы.
Ответ 5
Почему вы хотите реализовать свой собственный метод getClass()? Вы можете просто использовать
System.out.println(User.class);
Изменить (немного уточнить): вы хотите, чтобы метод был статическим. В этом случае вы должны вызвать метод в классе, имя класса которого вы хотите, будь то подкласс или суперкласс. Затем вместо вызова MyClass.getClass()
вы можете просто вызвать MyClass.class
или MyClass.class.getName()
.
Кроме того, вы создаете метод static
с той же сигнатурой, что и метод экземпляра Object.getClass()
, который не будет компилироваться.
Ответ 6
Мне повезло с
this.getClass().asSubclass(this.getClass())
Но я не уверен, как это работает.
Ответ 7
- Создать элемент Строковая переменная в суперклассе.
- Добавьте this.getClass(). getName() в конструктор, который сохраняет значение в переменной String элемента.
- Создайте getter, чтобы вернуть имя.
Каждый раз, когда экземпляр расширенного класса создается, его имя будет сохранено в String и доступно с помощью получателя.
Ответ 8
Статический метод связан с классом, а не с конкретным объектом.
Посмотрите, как это будет работать, если существует несколько подклассов - например, Администратор также является Сущностью. Как бы ваш статический метод Entity, связанный только с классом Entity, знал, какой подкласс вам нужен?
Вы можете:
- Использовать существующий метод getClass().
- Передайте аргумент вашему статическому методу getClass() и вызовите метод экземпляра для этого объекта.
- Сделайте свой метод нестатичным и переименуйте его.
Ответ 9
Если я правильно понимаю ваш вопрос, я думаю, что единственный способ добиться того, что вы хотите, - это повторно реализовать статический метод в каждом подклассе, например:
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 по мере необходимости. Грустно, но эй, если это ваши ограничения...
Ответ 10
Если я правильно понимаю, вы хотите использовать свой подкласс в базовом классе в статическом методе
Я думаю, вы можете сделать это, передав параметр класса методу
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);
}
}
Ответ 11
My context: superclass Entity с подклассами для объектов XML.
Мое решение:
Создайте переменную класса в суперклассе
Class<?> claz;
Тогда в подклассе я установил бы переменную суперкласса в конструкторе
public class SubClass {
public SubClass() {
claz = this.getClass();
}
}
Ответ 12
это очень просто сделать с помощью
User.getClass(). GetSuperclass()