Reputation: 193
I have methods like this:
public File method1(){
method2()
}
public method2(){
do something..
and get method1 return type(in this case File)
}
How do I get it? i tried like this..
Throwable t = new Throwable();
StackTraceElement[] elements = t.getStackTrace();
and get all the methods for the elements. And after that, getReturnType
, but it doesn't work. I also tried
public File method1(){
method2(this.getClass());
}
public method2(Class<?> className){
//problem here
}
But here the problem is that i can't compare two elements, the one on the stack and the one from classname.getMethods()
.
Is there any way that I can send method return type to a method2
? I need this because of making some history-like log. I know it can be done with aspectJ but I have to do it somehow like this.
EDIT:
The main problem I have is that I can get stack output, and see the method who called my method2 - that's one fragment I need! Also I need that method's return type, but the stack doesnt hold that information. Now, I can get all the methods from the class where the "method who called method2" is. The list of those methods, hold everything, return type, input parameters.. but that's a pretty big list, 63 methods. So I have to compare them somehow to find out which one is the one FROM STACK. I can't comapre them using name, because some differ with return type, hashcode is different - that's where I'm stuck.
Upvotes: 1
Views: 3045
Reputation: 2533
Updated answer
Using combination of StackTrace and Reflection
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Vector;
public class CallingMethodReturnType
{
public static void main( String[] args )
{
CallingMethodReturnType app = new CallingMethodReturnType();
app.method1();
app.method3();
}
public File method1(){
method2();
return null;
}
public ArrayList method3(){
method4();
return null;
}
public Vector method4() {
method2();
return null;
}
public void method2(){
Method method;
try {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement ste = stackTraceElements[2];
String callerMethodName = ste.getMethodName();
method = this.getClass().getMethod(callerMethodName, null);
Class returnType = method.getReturnType();
System.out.println(returnType);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
Also check question How do I find the caller of a method using stacktrace or reflection? if you are concerned with performance.
Original answer
You can use reflection API like this
public method2(){
//do something and get method1 return type(in this case File)
Method method = this.getClass().getMethod("method1", null);
Class returnType = method.getReturnType();
}
Upvotes: 0
Reputation: 1074168
Update
If you really need to do this from a stack trace (which I would strongly recommend avoiding), I don't think you can. The stack trace can tell you the class and method names, but it doesn't include the method's argument types, and so if the method is overloaded you can't tell which one called method2
.
I recommend you revisit your design. If method2
needs to know the return type of the method that calls it, then the method in question should pass that information into method2
. Attempting to gather that information from a runtime stack is not only inefficient, but it's a design red flag.
Example:
public File method1(File f) {
// ...
method2(File.class);
}
public String method1(String s) {
// ...
method2(String.class);
}
public Foo method1(Foo f) {
// ...
method2(Foo.class);
}
There we have three overloads of method1
. This is not a problem for method2
, because each of them tells method2
what its return type is — or more accurately, I hope, what it needs method2
to create for it or whatever.
Original answer
For the specific case you list (esp. toward the end of your question), you can do this:
public File method1(){
method2(File.class);
}
File.class
is the Class
instance for the File
class.
For the general case of finding the type of the return value of a method in a class, you can use the reflection API. Get the Class
instance for the class containing the method via Class.forName
, look up the method on that Class
instance using Class#getMethod
, then use Method#getReturnType
on that Method
to find out the return type's class.
Upvotes: 2
Reputation: 2969
If the class you are returning has an empty constructor, you could build a instance of the return type locally in method2() and use that, but that is dangerous and not generic.
You could do x.getClass().getName() and perform a switch operation.
What I would suggest, though, is that you consider rearchitecting this to use AspectJ and put a cut point in your parent call to collect the information you really want before you get too low in the stack. I'm guessing a little bit as to your intent, but any time you are parsing the stack output for type information I think the design deserves a second look.
Upvotes: 0
Reputation: 62583
Why is it so difficult with reflection?
public File method1() {
method2()
}
public void method2() {
Class<?> returnType = this.getClass().getMethod("method1").getReturnType();
}
Of course, you'll have to handle the exceptions though.
Upvotes: 2