Getting the name of a sub-class from within a supe

2019-01-22 16:37发布

Let's say I have a base class named Entity. In that class, I have a static method to retrieve the class name:

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

Now I have another class extend that.

class User extends Entity {
}

I want to get the class name of User:

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

My goal is to see "com.packagename.User" output to the console, but instead I'm going to end up with "com.packagename.Entity" since the Entity class is being referenced directly from the static method.

If this wasn't a static method, this could easily be solved by using the this keyword within the Entity class (i.e.: return this.class.getClass()). However, I need this method to remain static. Any suggestions on how to approach this?

12条回答
混吃等死
2楼-- · 2019-01-22 17:07

Not possible. Static methods are not runtime polymorphic in any way. It's absolutely impossible to distinguish these cases:

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

They compile to the same byte code (assuming that the method is defined in Entity).

Besides, how would you call this method in a way where it would make sense for it to be polymorphic?

查看更多
男人必须洒脱
3楼-- · 2019-01-22 17:07

If i am taking it right you want to use your sub class in base class in static method I think you can do this by passing a class parameter to the method

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);
    }
}
查看更多
小情绪 Triste *
4楼-- · 2019-01-22 17:16

If I understand your question correctly, I think the only way you can achieve what you want is to re-implement the static method in each subclass, for example:

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

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

This will print package.Entity and package.Derived as you require. Messy but hey, if those are your constraints...

查看更多
姐就是有狂的资本
5楼-- · 2019-01-22 17:16

My context: superclass Entity with subclasses for XML objects. My solution: Create a class variable in the superclass

Class<?> claz;

Then in the subclass I would set the variable of the superclass in the constructor

public class SubClass {
   public SubClass() {
     claz = this.getClass();
   }
}
查看更多
爷的心禁止访问
6楼-- · 2019-01-22 17:18

Don't make the method static. The issue is that when you invoke getClass() you are calling the method in the super class - static methods are not inherited. In addition, you are basically name-shadowing Object.getClass(), which is confusing.

If you need to log the classname within the superclass, use

return this.getClass().getName();

This will return "Entity" when you have an Entity instance, "User" when you have a User instance, etc.

查看更多
你好瞎i
7楼-- · 2019-01-22 17:20

The superclass should not even know of the existence of the subclass, much less perform operations based on the fully qualified name of the subclass. If you do need operations based on what the exact class is, and can't perform the necessary function by inheritance, you should do something along these lines:

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

(Untested code)

This class doesn't know about its own subclasses, either, but rather uses the Class class to perform operations. Most likely, it'll still be tightly linked with implementations (generally a bad thing, or if not bad it's not especially good), but I think a structure like this is better than a superclass figuring out what all of its subclasses are.

查看更多
登录 后发表回答