11

In reference to Java, I would like to statically know the class name of the current class. A is the parent class of B. I would like to have a static String in A (parent class) which contains the class name of the current class, but when this static String is referenced in B (child class), it should contain the class name of B. Is this possible?

Example:

public class Parent {

protected static String MY_CLASS_NAME = ???
.
.
.
}

public class Child extends Parent {

public void testMethod() {
     if (MY_CLASS_NAME.equals(getClass().getName())) {
        System.out.println("We're equal!");
     }
}

}
ChaimKut
  • 2,759
  • 3
  • 38
  • 64
  • why would you do that as you can get class name in other ways? – Feras Odeh Jan 16 '11 at 13:36
  • 2
    I have sometimes wished that this were possible, too. But it isn't. The word `static` already means that a member/method, etc is *statically* linked to the class that holds it. You cannot override it - as when linking is done *dynamically* for instance members/methods – Lukas Eder Jan 16 '11 at 13:45
  • possible duplicate of [Abstract variables in Java?](http://stackoverflow.com/questions/2371025/abstract-variables-in-java) – BalusC Jan 16 '11 at 13:59
  • How would you use it, the test method does not really say much. – josefx Jan 16 '11 at 14:56
  • I'm writing an API for other developers to use and I want some way to verify the package name, class of the various plugins using the API. I was planning on having developers subclass the parent class and passing this static string to our service along with the various requests. (Admittedly, the string could probably accomplish the same goal more easily without being static). Any other suggestions how to accomplish this goal? Looks like it's starting to turn into a design question... – ChaimKut Jan 17 '11 at 10:00

3 Answers3

9

The only way I know is the following: create protected constructor that accepts String in parent class.

class Parent {
    private final String className;
    protected Parent(String className) {
         this.className = className;
    }
}

public class Child extends Parent {
    public Child() {
        super("Child");
    }
}

BTW you can even improve this using new Throwable().getStackTrace() in paren's custructor. In this case you even do not have to enforce all children to pass their name to parent.

class Parent {
    private final String className;
    protected Parent() {
         StackTraceElement[] trace = new Throwable().getStackTrace();
         this.className = trace[1].getClassName();
    }
}
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Oooh, that smells fishy! `trace[1].getClassName();` ... Nice idea though :) – Lukas Eder Jan 16 '11 at 13:49
  • 1
    If you want to go this hacky direction anyway, I'd rather use `Thread#getStackTrace()` since that saves you from unnecessary and relatively expensive construction of the exception and cloning of the stacktrace. Providing an abstract constructor taking an argument is IMO the way to go. – BalusC Jan 16 '11 at 13:57
  • @BalusC: The disadvantage of the abstract constructor is, that each instance contains one copy of the string - which is a waste of memory compared to a static field. – Chris Lercher Jan 16 '11 at 14:05
  • @Chris: It's negligible if you make the string a constant. See also your own answer and the linked possible dupe. – BalusC Jan 16 '11 at 14:05
  • @BalusC: Depends - it's still 4 bytes for the pointer. For lots of small objects in a tree (e.g. DOM like structures), I prefer to avoid it, because I don't see a real advantage :-) – Chris Lercher Jan 16 '11 at 14:09
  • @Chris: the advantage is that it can be checked at compiletime. – BalusC Jan 16 '11 at 14:10
  • @BalusC: That's also true for my solution: Just define getName() as abstract. – Chris Lercher Jan 16 '11 at 14:12
  • @Chris: ah yes, that's even better. – BalusC Jan 16 '11 at 14:16
5

No, that's not possible. There's only one copy of the static String (per ClassLoader), but you can have multiple subclasses.

You can however have a static field per (sub-)class, and then use a method

public class Child extends Parent {
   private static final String NAME = "some alias";

   @Override
   public String getName() {
       return NAME;
   }
}

This is a technique that can be used to avoid Reflection (the NAME then often doesn't equal the class name, but uses some alias - it can also be used with enums instead of Strings).

Chris Lercher
  • 37,264
  • 20
  • 99
  • 131
1

try this code although you could not do it using static variable

  class Parent{
    final String className;
    public Parent(){
     className=this.getClass().getName();
    }
  }

and do that for required subclasses

Feras Odeh
  • 9,136
  • 20
  • 77
  • 121