【问题标题】:Java: boolean primitive private method returning false even though set to trueJava:即使设置为true,布尔原始私有方法也返回false
【发布时间】:2014-12-18 03:57:37
【问题描述】:

我有一个调用私有方法的公共方法,它有条件地调用另一个私有方法。所有这三种方法都返回一个布尔原始值,但是该值有时会与我期望的不同。

我确信我遗漏了一些非常明显的东西,但我现在离代码太近了,看不到问题所在。

这是代码的清理示例版本和我看到的结果:

编辑:我在底部添加了实际代码

public class MyClass { 

    // Default Constructor
    public MyClass() {}

    public boolean foo(final Object arg0, final Object arg1, final Object arg2) { 
        final boolean result = this.bar(arg0, arg1, arg2); 
        System.out.println("foo: " + result);
        return result;
    } 


    private boolean bar(final Object arg0, final Object arg1, final Object arg2) { 
        boolean result = false;
        System.out.println("bar: " + result); 

        try {  
            // complicated code that could generate an exception

            if (this.wowsers(arg0, arg1, arg2)) {
                result = true;
                System.out.println("bar: " + result); 
                System.out.println("bar: call to wowsers() returned true"); 
            }

        } catch (Exception e) { 
            System.out.println("SOMETHING BLEW UP");
            e.printStackTrace();
        } finally { 
            // This should NOT change result
            this.irrelevantMethod_1(null);
            this.irrelevantMethod_2(null);
            this.irrelevantMethod_3(null);
        } 

        System.out.println("bar: " + result); 
        return result;
    } 

    private boolean wowsers(final Object arg0, final Object arg1, final Object arg2) { 
        boolean result = false;

        // complicated code involving the passed in arguments
        // this MIGHT change result

        System.out.println("wowsers: " + result); 
        return result;
    }

    private void irrelevantMethod_1(Object arg0) { 
        // Nothing in here to change result 
    } 

    private void irrelevantMethod_2(Object arg0) { 
        // Nothing in here to change result 
    } 

    private void irrelevantMethod_3(Object arg0) { 
        // Nothing in here to change result 
    } 
} // END Class MyClass

调用代码:

MyClass myInstance = new MyClass(); 
myInstance.foo(); 

控制台输出:

> bar: false
> wowsers: true 
> bar: true
> bar: call to wowsers() returned true 
> foo: false

在上面的示例中,结果的值在方法 dowsers() 中设置为 true,并正确返回到 bar()。当 bar() 测试 wowsers() 的返回值并发现它为 true 时,它​​将自己的结果设置为 true,并将 result 的值打印到控制台,并打印 dowsers() 返回的值为 true。

bar() 末尾的 System.out.println 永远不会执行(至少我从未在控制台中看到任何显示),并且 result 的值(此时为 true)返回为 false .

foo() 方法然后打印它从对 bar 的调用中接收到的值,该值始终为 false。

有人知道我在哪里搞砸了吗?

编辑:这是实际代码 - 替换方法 foo() 和 bar()

public boolean sendReminderNotifcation(final RequestController controller, final Session session, final Request request,
        final Comment comment, final boolean treatAsNewNote) {

    final boolean result = this.sendNotification(controller, session, request, comment, null, MailType.Remind, treatAsNewNote);
    System.out.println("sendReminderNotifcation(): " + result);
    System.out.println("***");
    return result;
}



private boolean sendNotification(final RequestController controller, final Session session, final Request request,
        final Comment comment, final TreeSet<String> copyto, final MailType mailtype, final boolean treatAsNewNote) {

    HashMap<NotifyWhom, TreeSet<String>> sendTo = null;
    boolean result = false;

    System.out.println("sendNotification(): " + result);

    try {
        if (null == controller) { throw new IllegalArgumentException("RequestContoller is null"); }

        this.setRequestURLprefix(controller.getRequestURLprefix());

        if (null == session) { throw new IllegalArgumentException("Session is null"); }
        if (null == request) { throw new IllegalArgumentException("Request is null"); }
        if (null == mailtype) { throw new IllegalArgumentException("mailtype is null"); }

        final EnumSet<NotifyWhom> recipients = this.getRecipients(controller, session, request, mailtype, treatAsNewNote);

        if ((null == recipients) || recipients.isEmpty()) { return false; }

        final HashMap<NotifyWhom, TreeSet<String>> tempSendTo = this.getSendTo(controller, request, recipients);
        if (null == tempSendTo) { throw new RuntimeException("NO RECIPIENTS FOR NOTIFICATION"); }

        // clear out any duplicates
        sendTo = this.purgeDuplicateRecpients(tempSendTo);

        // Update Prior Assignee Information
        // Update Requestor Information
        // Update Queue Owner Information
        this.updateReOpenedInformation(controller, session, request);

        final String subject = (request.isReOpened()) ? HelpdeskNotifications.SUBJECT_REOPENED : HelpdeskNotifications.SUBJECT_UPDATED;

        final Iterator<Entry<NotifyWhom, TreeSet<String>>> sit = sendTo.entrySet().iterator();
        final TreeSet<NameHandle> exclude = this.getExcludeRecipients();
        while (sit.hasNext()) {
            final Map.Entry<NotifyWhom, TreeSet<String>> entry = sit.next();
            final MailNotifyKey key = new MailNotifyKey(this.getLogger(), mailtype, entry.getKey());
            if (MailType.Remind.equals(mailtype)) {
                final Status status = request.getStatus();
                final MailRecipientOption mro = (null == status) ? null : status.getMailRecipientOption(key);

                // A null mro indicates that Notifications are DISABLED
                if (null == mro) { return false; }
            }

            final TreeSet<String> sendto = entry.getValue();
            if (this.sendEmail(controller, session, request, subject, comment, sendto, copyto, exclude, key, treatAsNewNote)) {
                result = true;
                System.out.println("sendNotification(): " + result);
                System.out.println("sendNotification(): (call to sendEmail() returned true)");
            }
        }

        // Send Special Re-Opened Notifications
        if (this.sendReOpenedNotifications(controller, session, request, subject, comment, treatAsNewNote)) {
            result = true;
            System.out.println("sendNotification(): " + result);
            System.out.println("sendNotification(): (call to sendReOpenedNotifications() returned true)");
        }

    } catch (final Exception e) {
        this.getLogger().logException(this, e);
        e.printStackTrace();
    } finally {
        this.setPriorAssigneeNotify(null);
        this.setReOpenedRecipients(null);
        this.setExcludeRecipients(null);
    }

    System.out.println("sendNotification(): " + result);
    return result;
}

我得到的控制台输出是:

> sendNotification(): false 
> sendNotification(): true 
> sendNotification(): (call to sendEmail() returned true) 
> sendReminderNotifcation(): false 
> ***

(我意识到我应该首先发布实际代码)

由于某种原因,我无法弄清楚,方法 bar() 和方法 sendNotification() 中的最后两行代码似乎没有运行。是否有其他方法可以完成并返回我不知道的方法?

【问题讨论】:

  • 第三个bar + result 日志不包含在您的控制台输出中,但没有任何迹象表明可以跳过它,因为没有提前返回,也没有允许foo 登录的捕获块单独执行。
  • 是的,完全正确。这是我想不通的事情之一。它应该出现,但事实并非如此。我检查了又检查了一遍,确保方法中没有其他return语句,找不到。
  • 您粘贴的代码中肯定缺少某些内容。
  • 你是在调试器中一步一步运行的吗?
  • 我猜你实际上是从 finally 块返回一些东西。您应该提供一个完整的、可重现的测试用例。

标签: java boolean return primitive


【解决方案1】:

我建议你在这行之前放一个调试打印语句:

              if (null == mro) { return false; }

因为这是在一个while循环中,并且允许该方法返回false,即使result已被设置为true。我敢打赌,这就是错误返回的来源,也是您看不到正在执行的最终打印语句的原因。

【讨论】:

  • 宾果游戏。感谢您解决这个问题。
  • 如何在一个while循环中让它返回false,即使它是真的?
  • @Joza100 这与它在while循环中的事实无关。 result 变量并没有什么特别之处,声明中写的是return false 而不是return result。如果您特别有一个声明说return false,那么它会这样做。它在循环中的事实解释了为什么对 sendEmail 的调用确实在 sendNotification 方法本身返回 false 之前执行(并返回 true) - 因为这发生在第二次迭代中。
【解决方案2】:

阅读:

Is Java "pass-by-reference" or "pass-by-value"?

在这个方法中

private boolean wowsers(final Object arg0, final Object arg1, final Object arg2) { 
    boolean result = false;

    // complicated code involving the passed in arguments
    // this MIGHT change result

    System.out.println("wowsers: " + result); 
    return result;
}

您重新实例化布尔变量。这是一个新的布尔值result 超出范围方法bar

简单地阻止。想想吧。

            result = true;
            System.out.println("bar: " + result); 

最后它看起来像一个

private boolean bar(final Object arg0, final Object arg1, final Object arg2) { 
    boolean result = false;
    // no reassignee result value
    return result; 
}

所以你返回 false

【讨论】:

  • 感谢您的回答。我已经更新了原始问题以包含实际代码。我不确定我是否完全理解您的答案,因为我没有将结果的值传递给方法,只是返回它。范围应该是本地的,并且在每个方法内部都是独立的,并且返回的值。如果我在这里误解,请解释。
  • 尝试将 synchronized 添加到两个方法修饰符中。
【解决方案3】:
final boolean result

这意味着你希望结果在它的第一个值之后永远不会改变。

这就是你得到的。 删除final。

【讨论】:

  • 最终布尔结果是有意的,它只是作为方法变量存在,以便我可以记录函数调用的结果。它一旦设置就不会更改,因此是 final 的原因。
猜你喜欢
  • 2020-06-23
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
相关资源
最近更新 更多