【问题标题】:Can I use an If statement to check which method made the call?我可以使用 If 语句来检查哪个方法进行了调用吗?
【发布时间】:2013-10-05 06:56:04
【问题描述】:

我想创建一个 if 语句来检查哪个方法调用了辅助方法。

我会用伪代码写出我想要的,这样你就能明白我的意思了。

public static void methodOne() {
    methodToCall();
    }

public static void methodTwo() {
    methodToCall();
    }

public static void methodThree() {
    methodToCall();
    }

public static void methodToCall() {
    if (methodOne made the call == true) {
        execute this
    } else if (methodTwo made the call == true){
        execute this
    } else if (methodThree made the call == true){
        execute this
    } else {
        System.out.println("How did you get here?");
    }
}

这就是它的要点。我想要一个简单的检查来查看调用的方法,以便我可以选择与调用相关的操作。

这可能吗?

如果不可能,有解决办法吗?

【问题讨论】:

  • 为什么不直接传一个参数?
  • 为什么你首先将三个方法调用委托给一个,只是为了再次将它分开?
  • 耦合方法(或函数、类、程序...)是必要的,但必须受到控制并尽可能避免。
  • 全局变量?你从哪里来的?在 1970 年,好吧,我们别无选择,但今天,使用面向对象语言,全局变量被禁止了!

标签: java if-statement methods


【解决方案1】:

这被称为“国家导向”,在 1970 年代,甚至可能在 1960 年代,都进行了广泛的辩论。结论是,如果你需要知道这类事情,你已经在做一些严重错误的事情,通过在代码中引入双向依赖。例如,当您添加 另一个 调用者时会发生什么?

【讨论】:

    【解决方案2】:

    使用三个短方法,而不是将三个短方法的逻辑组合成一个更大的方法。创建短方法后,只需从每个调用方法中调用适当的方法即可。

    public static void methodOne() {
        methodToCall1();
    }
    
    public static void methodTwo() {
        methodToCall2();
    }
    
    public static void methodThree() {
        methodToCall3();
    }
    
    public static void methodToCall1() {
        int x = 0;
        x = x - 3; //some custom logic to prep argument
        commonLogic(x);
    }
    
    public static void methodToCall2() {
        //Method 2 logic
        int x = 0;
        x = x + 3; //some custom logic to prep argument
        commonLogic(x);
    }
    
    public static void methodToCall3() {
        //Method 3 logic
        int x = 0;
        x = x * 3; //some custom logic to prep argument
        commonLogic(x);
    }
    
    public static void commonLogic(int arg1){
         //peform common logic
    }
    

    如果这三个方法包含重复代码,请将重复代码抽象为另一个方法,然后从每个较小的方法中调用该方法。想法是准备参数以在三个较小函数中的每一个中调用公共函数,然后使用这些参数调用公共函数。

    【讨论】:

    • 这不是答案,因为问题不是问题... ;-)
    • @Aubin OP 确实询问是否有解决方法。顺便说一句,感谢您的编辑。
    • 解决方法存在(StckTre),但我不想写它,因为问题太模棱两可,动机也没有明确定义
    • @Aubin 同意,我在调试之前使用过该方法,但不会使用该方法做出合乎逻辑的决定。至少不是在这样容易解决的情况下。
    • @gcoulby 然后你创建另一个包含通用逻辑的方法。从三个单独的函数中调用该方法。所以基本上这三个小方法准备了要传递给通用函数的参数。
    【解决方案3】:

    方法提供的大量抽象来自于它们不需要知道谁在调用它们,因此您的问题的答案是“不”。但是,这并不意味着您不能让它工作:让调用者将某种令牌(例如,enum 值)传递给被调用者。这将允许您在方法的实现中分派该身份:

    enum CallerContext {CALLER1, CALLER2, CALLER3};
    ...
    public static void methodToCall(CallerContext context) {
        ...
    }
    

    不是最面向对象的做事方式,但是:通常情况下,更好的方法是让调用者提供要执行的逻辑,而不是提供标识逻辑。有关该方法的详细信息,请参阅Visitor Pattern

    【讨论】:

    • @dasblikenlight 我喜欢你传达的信息,但我不能保证我同意传递参数。为什么在简单地调用另一个方法时添加额外的包袱(参数)会捕获相同的意图。
    • @KevinBowersox 唯一有意义的情况是,在 if/then/else 检查呼叫者。这实质上变成了“穷人的双重派遣”。我认为 OP 在尝试提取他的问题代码时删除了太多细节,否则更小的、特定于调用者的函数会比单个大型函数更有意义。
    • 你说得对,我认为我的代码过于精炼了,但这仍然很有趣。我不知道这是可能的,但现在也知道这不是我的情况最推荐的方法,我可以看到在其他情况下可能需要它的原因,所以这是一个有效的答案
    【解决方案4】:

    你可以通过Thread.getStackTrace()检查调用堆栈来做到这一点:

    public static void methodToCall(Action action) {
        String callingMethod = Thread.currentThread().getStackTrace()[2].getMethodName();
        if (callingMethod.equals("methodOne")) {
            execute this0
        } else if (callingMethod.equals("methodTwo")) {
            execute this
        } else if (callingMethod.equals("methodThree")) {
            execute this
        } else {
            System.out.println("How did you get here?");
        }
    }
    

    但你不应该 - 这有点反 OO。相反,将您的方法签名更改为以下内容:

    public enum Action {ONE, TWO, THREE}
    
    public static void methodToCall(Action action) {
        if (action == ONE) {
            execute this
        } else if (action == TWO) {
            execute this
        } else if (action == THREE) {
            execute this
        } else {
            System.out.println("How did you get here?");
        }
    }
    

    【讨论】:

    • -1:必须将辩论视为更高级别时的“技术员”答案。即使有可能,是否可取?
    • @aubin 提出的问题是“可以做到”,而不是“应该没问题”。我展示了如何做到这一点。但我也说过你不应该。那么你到底不赞成什么?
    【解决方案5】:

    如果您最终使用枚举,那么请确保利用 Java 中的枚举不亚于类的单例实例这一事实。因此,您可以在枚举定义中将方法声明为抽象,然后在每个实例中覆盖它,而不是将枚举作为参数传递给在枚举上下文之外定义的某些方法。

    所以它看起来像:

    enum Method {
    
        Mode1 {
                @Override
                void call() {
                        // do stuff 
                }
        }, Mode2 {
                @Override
                void call() {
                        // do stuff differently
                }
        }, Mode3 {
                @Override
                void call() {
                        // do stuff even more differently
                }
        };
    
        abstract void call();
    }
    

    然后你要么不需要你的包装方法,或者,如果他们应该做更多的事情,你写:

    public static void methodOne() {
        // some code
        Method.Mode1.call();
        // some code
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      相关资源
      最近更新 更多