spr*_*ter 9 java debugging java-8 java-stream
我喜欢 Java 8流.它们直观,强大而优雅.但它们确实有一个主要的缺点IMO:它们使调试更加困难(除非你可以通过调试lambda表达式来解决你的问题,这在这里得到解答).
考虑以下两个等效片段:
int smallElementBitCount = intList.stream()
.filter(n -> n < 50)
.mapToInt(Integer::bitCount)
.sum();
Run Code Online (Sandbox Code Playgroud)
和
int smallElementBitCount = 0;
for (int n: intList) {
if (n < 50) {
smallElementBitCount += Integer.bitCount(n);
}
}
Run Code Online (Sandbox Code Playgroud)
我发现第一个更清晰,更简洁.但是请考虑结果不符合您预期的情况.你是做什么?
在传统的迭代样式中,您totalBitCount += Integer.bitCount(n);在行上放置一个断点并逐步浏览列表中的每个值.您可以看到当前列表元素是什么(监视n),当前总计(监视totalBitCount),以及根据调试器,Integer.bitCount的返回值是什么.
在新的流式中,所有这一切都是不可能的.您可以在整个语句中放置断点并逐步执行该sum方法.但总的来说这是无用的.在我测试的这种情况下,我的调用堆栈是11深,其中10个是我不感兴趣的java.util方法.不可能单步执行代码测试谓词或执行映射.
在调试流问题的答案中注意到,迭代调试器可以很好地破坏内部lambda表达式(例如n < 50谓词).但在许多情况下,最合适的断点不在lambda中.
显然,这是一段简单的调试代码.但是,一旦添加了自定义缩减和集合,或者更复杂的过滤器和映射链,它就会成为调试的噩梦.
我在NetBeans和Eclipse上试过这个,但两者似乎都有同样的问题.
在过去的几个月里,我习惯于使用.peek调用来记录临时值或将临时步骤移动到他们自己的命名方法中,或者在极端情况下,重构为迭代,直到任何错误被整理出来.这可以工作,但它让我想起了在使用集成交互式调试器的现代IDE之前的许多糟糕的旧时代,当你不得不通过代码分散printf语句时.
当然有更好的方法.
具体来说,我想知道:
您发现成功的任何技术都将非常感激.
我不完全确定是否有可行的解决方案来解决这个问题。据我所知,通过使用流,您可以有效地将迭代(以及相关代码)委托给虚拟机,从而将流程推入一个黑匣子,即流本身。
至少从我读到的有关它们的内容来看是这样。对我来说,这就是 lambda 代码周围发生的事情(如果它们足够复杂,则很难跟踪它们周围发生的事情)。我对任何调试选项都很感兴趣,但我个人还没有找到。
| 归档时间: |
|
| 查看次数: |
786 次 |
| 最近记录: |