95

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?

Matt Huggins
  • 81,398
  • 36
  • 149
  • 218

12 Answers12

113

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.

matt b
  • 138,234
  • 66
  • 282
  • 345
  • 1
    `this` does not exist in a static method. – Matt Huggins Aug 05 '10 at 19:03
  • 37
    @Matt Huggins, that is why the first sentence in my answer says `Don't make the method static` – matt b Aug 05 '10 at 20:10
  • 7
    @ matt b - that is why the second to last sentence of my question says `However, I need this method to remain static.` – Matt Huggins Jan 19 '12 at 02:05
  • @MattHuggins I wonder why a Pojo method would not work. If you are invoking a static method, you have to reference the class name already in the code. If you have instantiated the subclass but the reference is of the superclass, you have an object and do not need to call the static method. – Mindwin Remember Monica Jul 15 '15 at 14:52
  • 10
    Even though this answer doesn't address "However, I need this method to remain static", it is useful if (like me) you landed here looking for how to get the class in a method that did not need to be static. ;) – Ryan Heathcote Sep 30 '16 at 03:07
44

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?

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • 1
    Thanks for clarifying, I guess I do not know enough about how static methods compile. This helps clear things up, I'll have to work on an alternate solution. – Matt Huggins Aug 05 '10 at 19:04
  • 2
    +1, exactly right. This entire question is born out of a misunderstanding of how static methods work. – Mark Peters Aug 05 '10 at 19:28
11

This works for me

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

But I'm not sure how it works though.

sirolf2009
  • 819
  • 8
  • 15
7

Your question is ambiguous but as far as I can tell you want to know the current class from a static method. The fact that classes inherit from each other is irrelevant but for the sake of the discussion I implemented it this way as well.

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();
    }
}
Gilead
  • 1,516
  • 2
  • 18
  • 26
  • Ouch, that *stacktrace-hack* is dirty. What's wrong with `System.out.println(Parent.class.getName());`? – whiskeysierra Aug 05 '10 at 19:03
  • 2
    As I said, Matt's question is ambiguous and I provided one of the possible answers. Clearly your version doesn't give the same output as my code so there's no comparison -- you're talking about a different solution. And reading thread stack is not a hack, it's a normal way of checking one's call hierarchy (of course I skipped sanity check as this is an example). – Gilead Aug 05 '10 at 19:11
  • This is a pretty funny hack, but has little to do with the requested behaviour. This function prints the name of the class *calling* the method (i.e., if you remove `extends Parent` and change the call to `Parent.printClass()`, it still prints "Test"). – nemetroid Jul 25 '17 at 09:27
3
  1. Create a member String variable in the superclass.
  2. Add the this.getClass().getName() to a constructor that stores the value in the member String variable.
  3. Create a getter to return the name.

Each time the extended class is instantiated, its name will be stored in the String and accessible with the getter.

Dawg 'N IT
  • 31
  • 2
3

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.

Varun Bhatia
  • 4,326
  • 32
  • 46
Brian S
  • 4,878
  • 4
  • 27
  • 46
2

Why do you want to implement your own getClass() method? You can just use

System.out.println(User.class);

Edit (to elaborate a bit): You want the method to be static. In that case you must call the method on the class whose class name you want, be it the sub-class or the super-class. Then instead of calling MyClass.getClass(), you can just call MyClass.class or MyClass.class.getName().

Also, you are creating a static method with the same signature as the Object.getClass() instance method, which won't compile.

samitgaur
  • 5,601
  • 2
  • 29
  • 33
  • 1
    I intentionally wrote the question so it'd be very bare-bones on StackOverflow and get straight to the point of the question. It's really because I'm building a much more robust static method that utilizes the class name of whatever subclass extends this abstract base class. – Matt Huggins Aug 05 '10 at 18:32
  • 1
    Sounds like you want polymorphism through `static` methods, which is not possible. Also, can you elaborate why the above is not robust enough? – samitgaur Aug 05 '10 at 18:40
  • It's not robust enough because I would have to redefine the static method in every single inheriting class instead of just being able to define the static method once. – Matt Huggins Aug 05 '10 at 18:53
  • 1
    If you want to use static, you already know the concrete class. What's wrong with `User.class.getName()`? – whiskeysierra Aug 05 '10 at 19:05
  • Because if I hardcode `User.class.getName()` into `Entity`'s static method, then what will happen if I extend `Entity` with a new class called `Profile`? It will still return the class-name for User instead of the class-name for Profile. – Matt Huggins Aug 06 '10 at 07:55
0

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);
    }
}
Dis Honest
  • 77
  • 7
0

A static method is associated with a class, not with a specific object.

Consider how this would work if there were multiple subclasses -- e.g., Administrator is also an Entity. How would your static Entity method, associated only with the Entity class, know which subclass you wanted?

You could:

  • Use the existing getClass() method.
  • Pass an argument to your static getClass() method, and call an instance method on that object.
  • Make your method non-static, and rename it.
Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
0

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...

brabster
  • 42,504
  • 27
  • 146
  • 186
0

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();
   }
}
Matthias dirickx
  • 141
  • 2
  • 10
-4

it is very simple done by

User.getClass().getSuperclass()

NightGale
  • 40
  • 9
  • 2
    This does the opposite of what the question asked for. I wanted the name of a subclass from within a superclass. Your answer provides the name of the superclass from within a subclass. – Matt Huggins Oct 10 '12 at 00:25