views:

403

answers:

5

Consider this Java code

class A{
 //@returns Class object this method is contained in
 // should be A in this case
 public Class<?> f() {
   return getClass();
 }
}

class B extends A {}

B b = new B();

System.out.println(b.f());
//output -- B.class (Wrong, should be A.class)

inside f() i can't use getClass() because that will give me the runtype, which is B. I'm looking for a way to get the Class object of the class f() is inside (Without mentioning A explicitly, obviously)

+3  A: 

You can use exception stack trace facility to do something like this:

public String f() {
    Exception E = new Exception();
    E.fillInStackTrace();
    return E.getStackTrace()[0].getClassName(); // load it if you need to return class
}
ChssPly76
nice, that's really clever
Mike
You don't need exception to get stacktrace. This is much better way: Thread.currentThread().getStackTrace().
ZZ Coder
Actually, that doesn't work. Thread.currentThread().getStackTrace() populates the stack trace with Thread's own methods - dumpThreads() and getStackTrace() itself, though it possibly differs depending on JVM version / implementation.
ChssPly76
The only difference is that Thread's stack trace has one more element. Just use getStackTrace()[1];
ZZ Coder
Two more elements in java 1.5; and that may change depending on implementation. Now you can definitely go through stack trace and exclude all elements whose class is java.lang.Thread but at that point it's no longer easy and elegant; using exception seems easier.
ChssPly76
+1  A: 

You can use

class.getMethod("f",parameterTypes).getDeclaringClass()
sleske
This will only work for public methods; plus it's rather messy dealing with parameters.
ChssPly76
Is `class` supposed to be `getClass` (and `f` `final`)?
Tom Hawtin - tackline
You're both right. The approach using a stack trace is probably better. And of course it should be getClass (fixed). f need not be final however. Why should it need to be?
sleske
+2  A: 

I would have to say it would be much simpler and more clear to simply return A.class as @mmyers suggested. There is not much point in trying to derive it at runtime if you don't actually want the runtime value. The only issue that comes up is if you refactor the name of the class and another with the same name happens to exist, in the same package.

I would take that chance for the sake of clarity in the code now.

Robin
Exactly. The derivative answers are over-complicating things.
aberrant80
+4  A: 

new Object() {}.getClass().getEnclosingClass(). But please don't!

Tom Hawtin - tackline
Now that is cleaver!
Yishai
Yeah, I learnt it from someone else.
Tom Hawtin - tackline
+1  A: 

I know you said you didn't want to mention A.class explicitly

class A {        
    public Class<?> f() {
        return A.class;
    }   
}

but I'm struggling to find a use case where the above code isn't satisfactory.

Duncan McGregor