4

如何在java中获取方法的所有可能返回值?

例子:

Object onEvent() {
 if (condition) {
     return "a";
 }

 if (condition2) {
    return "b";
 }

 if (condition3) {
     return "c";
 } 

}

我需要这样的东西:

String[] returns = Utils.getReturnStatements("object.onEvent()");
returns = ["a", "b", "c"]
4

7 回答 7

5

只能检索方法签名,在这种情况下将Object作为返回类型。

要获取更多详细信息,您需要静态分析源代码或返回类型,例如enum.

于 2013-08-15T20:43:14.850 回答
4

如果您只需要分析返回常量值的简单方法(例如示例中的方法),那么您可以通过使用 ASM 或类似字节码工具包的静态分析相对轻松地完成此操作。

对于与示例结构匹配的方法(即仅直接返回常量),您只需要查找模式

LDC ???
ARETURN

并收集加载了 LDC 的常量。这将非常简单。

如果方法可能更复杂,例如,如果它们返回分配给变量的值,那么您将需要执行流分析。这是更多的工作,但 ASM 提供了支持。

如果您正在分析的方法返回的值不是简单的常量,那么通过静态分析来做到这一点将非常困难/不可能。

于 2013-08-15T21:17:02.110 回答
1

你不能在 Java 中做这样的事情,但你可以做这样的事情:

Object onEvent() {

    List<String> list = new ArrayList<String>();    

    if (condition) {
        list.add("a");
    }

    if (condition2) {
        list.add("b");
    }

    if (condition3) {
        list.add("c");
    }

    return list.toArray();

}

接着:

String[] returns = (String[])MyObj.onEvent();
于 2013-08-15T20:46:00.677 回答
1

正如@Johan 所说,这是不可能的。如果您真的需要,唯一的方法是将这些可能的结果存储在 Map 中,将方法名称映射到 List 或数组,或者如果可能,最好使用枚举。

编辑:

阅读您的评论后,我认为您应该使用 HashMap 以 Node 作为键和 List 作为值。分析节点时,您会在列表中创建退出节点列表,然后将该列表映射到节点。

于 2013-08-15T20:48:52.183 回答
1

首先删除多个返回:

此外,要获取所有返回类型,只需将对象列表传递给您的方法并更改如下onEvent代码:

Object onEvent(List<Object> rets) {
 String ret = "";
 rets.add("a");
 rets.add("b");
 rets.add("c");

 if (condition) {
     ret = "a";
 }

 if (condition2) {
    ret = "b";
 }

 if (condition3) {
     ret = "c";
 } 
 return ret;
}

像这样调用 onEvent:

List<Object> returns = new ArrayList<Object>();
Object retVal = obj.onEvent(returns);
于 2013-08-15T20:49:40.230 回答
0

使用命令模式,enum有一个解决方法。

public class OnEvent implements Command<EventInfo> {

    @Override
    public EventInfo execute() {
        // do some checking
        return EventInfo.A;
    }

    @Override
    public EventInfo[] getValues() {
        return EventInfo.values();
    }


    public static void main(String[] args) {
        OnEvent e = new OnEvent();
        EventInfo retVal = e.execute();
        EventInfo[] values = Utils.getReturnStatements(e);
    }

}

enum EventInfo {
    A, B, C;
}

interface Command<TYPE extends Enum<?>> extends KnownReturnValues<TYPE> { public TYPE execute(); }

interface KnownReturnValues<TYPE> { public TYPE[] getValues(); }

class Utils {

    private Utils() {}

    public static <TYPE extends Enum<?>> TYPE[] getReturnStatements(Command<TYPE> c) {
        return c.getValues();
    }
}
于 2013-08-15T21:06:48.003 回答
-1

它不是很好的编程实践,但您可以创建一个具有 3 个公共数据成员的类,并让您的代码看起来像这样。(我会称这个类为“myclass”)

public a, b, c = null;

//And then your main class would look something like this
if (condition){
  myclass.a=whatever;
}
else if (condition){
  myclass.b=whatever;
}
else if (condition){
  myclass.c=whatever
 }

然后,您将需要另一个控制结构,该结构表示类似于 if (myclass.datamember!=null) 的内容,以确保您在类数据成员中具有值。同样,这不是好的编程实践,但它可以满足您的需求。

于 2013-08-15T21:22:16.187 回答