Java IntelliJ IDEA调试多次输入方法

Java IntelliJ IDEA调试多次输入方法,java,debugging,intellij-idea,dynamic-proxy,Java,Debugging,Intellij Idea,Dynamic Proxy,调试以下代码时: public class MyProxy { public static void main(String[] args){ Consumer f = (Consumer) Proxy.newProxyInstance( Consumer.class.getClassLoader(), new Class[] { Consumer.class }, new

调试以下代码时:

public class MyProxy {
    public static void main(String[] args){

        Consumer f = (Consumer) Proxy.newProxyInstance(
                Consumer.class.getClassLoader(),
                new Class[] { Consumer.class },
                new Handler(new ConsumerImpl())
        );

        f.consume("Hello");   // set breakpoint here
        System.out.println("done");
    }
}

interface Consumer {
    void consume(String s);
}

class ConsumerImpl implements Consumer {
    public void consume(String s) {
        System.out.println(s);
    }
}

class Handler implements InvocationHandler {
    private final Consumer original;
    public Handler(Consumer original) {
        this.original = original;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws IllegalAccessException, IllegalArgumentException,
            InvocationTargetException {
        System.out.println("BEFORE");
        method.invoke(original, args);
        System.out.println("AFTER");
        return null;
    }
}
输出为:

BEFORE
AFTER
BEFORE
AFTER
BEFORE
BEFORE
AFTER
Hello
BEFORE
AFTER
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
BEFORE
AFTER
BEFORE
Hello
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
当调试器在断点行暂停时,输出已经有两行,当我进入invoke方法时,输出如图所示。这就像调试器在我做的每一步都输入invoke方法一样。因为如果我不进入该方法,则输出为:

BEFORE
AFTER
BEFORE
AFTER
BEFORE
BEFORE
AFTER
Hello
BEFORE
AFTER
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
BEFORE
AFTER
BEFORE
Hello
AFTER
BEFORE
AFTER
done
BEFORE
AFTER
如果我运行代码,输出将如预期的那样

BEFORE
Hello
AFTER
done
这是调试器的错误还是我做错了什么


Env:windows64、intellijidea、JDK8这不是IDEA中的bug。如果尝试在没有任何断点的情况下对此进行调试,可能会得到与预期相同的结果。 但如果您放置一些断点,IDEA将尝试调用toString方法,然后调用它可以计算的变量的hashCode方法


最终,对于所有方法,它将调用您的InvocationHandler实现—不仅对于consume方法,您还可以打印method.getName,以确保在InvocationHandler实现中做到这一点。

这不是IDEA中的错误。如果尝试在没有任何断点的情况下对此进行调试,可能会得到与预期相同的结果。 但如果您放置一些断点,IDEA将尝试调用toString方法,然后调用它可以计算的变量的hashCode方法


最终,对于所有方法,它将调用您的InvocationHandler实现—不仅对于consume方法,您还可以打印method.getName,以确保在InvocationHandler实现中做到这一点。

我是否正确理解这一点:1。在调试时,我所做的每一步,调试器都会通过调用作用域中的toString和hashCode来重新计算每个变量,以刷新其值。2.在invoke方法中一步一步地进行计算时,会对其进行计算,产生与在main中计算f相同的效果。我使用method.getName进行了测试,只调用toString进行计算,没有hashCode。是的,在您的情况下,它只是toString方法。我的答案的第一段只是关于泛型的问题,如果它是一个普通类,如果您没有重写toString,那么hashCode方法将通过toString方法执行。我想我的答案对hasCode方法有点不清楚。@hunter您能给我一个详细的例子来详细解释一下吗。在我的Grails控制器中,我有一个showid方法,当我的方法有断点时,它在调试模式下调用了3次。在没有断点的情况下,它在调试模式下工作正常。我想知道它的原因。我是否理解正确:1。在调试时,我所做的每一步,调试器都会通过调用作用域中的toString和hashCode来重新计算每个变量,以刷新其值。2.在invoke方法中一步一步地进行计算时,会对其进行计算,产生与在main中计算f相同的效果。我使用method.getName进行了测试,只调用toString进行计算,没有hashCode。是的,在您的情况下,它只是toString方法。我的答案的第一段只是关于泛型的问题,如果它是一个普通类,如果您没有重写toString,那么hashCode方法将通过toString方法执行。我想我的答案对hasCode方法有点不清楚。@hunter您能给我一个详细的例子来详细解释一下吗。在我的Grails控制器中,我有一个showid方法,当我的方法有断点时,它在调试模式下调用了3次。没有断点,它在调试模式下工作正常。我想知道它的原因。