Когда-то приятными маленькими особенностями большинства отладчиков, которыми я занимался в последнее время, является возможность записывать информацию в точку останова. Это может быть действительно полезным, чтобы понять код без необходимости его изменения, это связано с модификацией байтового кода.
Давайте рассмотрим эту очень тривиальную и неэффективную реализацию функции для возврата n-го числа в последовательности Фибоначчи.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public class Fib { public long fib( long number) { return number < 1 ? 0 : // Breakpoint here number < 2 ? 1 : fib(number - 2 ) + fib(number - 1 ); } public static void main(String[] args) { Fib fib = new Fib(); System.out.println(fib.fib(10L)); } } |
Теперь мы добавляем простую точку останова, я собираюсь немного ее изменить, чтобы она не остановилась; но он будет записывать простое выражение, которое дает нам текущее значение number
Это дает следующий вывод для нашего довольно неэффективного кода:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
ebugger connected to local process. Source breakpoint: Fib.java: 11 , evaluate(number)= 10 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 8 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 6 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 4 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 2 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 0 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 1 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 3 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 1 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 2 ( long ) ... sometime later Source breakpoint: Fib.java: 11 , evaluate(number)= 1 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 2 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 0 ( long ) Source breakpoint: Fib.java: 11 , evaluate(number)= 1 ( long ) 55 |
Итак, что мы сделали здесь, так это добавили трассировку post-hoc, вы можете даже не иметь доступа к источнику и все же иметь возможность получить полезную информацию о том, что делает код.
Теперь очевидный вывод из приведенного выше примера состоит в том, что мы вычисляем одно и то же значение снова и снова. Итак, вот еще одна версия кода, которая вместо этого использует карту для хранения ранее вычисленных значений в последовательности. Заметьте также, что добавление трассировки в этот код труднее, чем в предыдущем случае, не делая Lambda менее привлекательной.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import java.util.HashMap; import java.util.Map; public class Fib { Map<Long, Long> data = new HashMap<>(); { data.put(1L, 1L); } public long fib( long number) { return data.computeIfAbsent(number, n -> n < 1 ? 0 : fib(n - 2 ) + fib(n - 1 )); // Breakpoint here } public static void main(String[] args) { Fib fib = new Fib(); System.out.println(fib.fib(10L)); } } |
Здесь стоит отметить две вещи: во-первых, ваше выражение журнала точек останова должно оценивать значение лямбда-параметра n
а во-вторых, вы всегда должны помещать свое выражение в новую строку, чтобы будущий разработчик мог легко его установить. (Неважно, теперь намного меньше / красивее / умнее, это выглядело бы, если бы вы поместили код в один).
Таким образом, вывод трассировки теперь выглядит намного лучше, поскольку каждое значение вычисляется только один раз.
01
02
03
04
05
06
07
08
09
10
11
12
|
Debugger connected to local process. Source breakpoint: Fib.java: 17 , evaluate(n)= 10 Source breakpoint: Fib.java: 17 , evaluate(n)= 8 Source breakpoint: Fib.java: 17 , evaluate(n)= 6 Source breakpoint: Fib.java: 17 , evaluate(n)= 4 Source breakpoint: Fib.java: 17 , evaluate(n)= 2 Source breakpoint: Fib.java: 17 , evaluate(n)= 0 Source breakpoint: Fib.java: 17 , evaluate(n)= 3 Source breakpoint: Fib.java: 17 , evaluate(n)= 5 Source breakpoint: Fib.java: 17 , evaluate(n)= 7 Source breakpoint: Fib.java: 17 , evaluate(n)= 9 55 |
Снимки экрана в этом блоге от Jdeveloper; но аналогичные функции доступны в Intelij , Netbeans, и если вы немного хитры , вы можете получить нечто подобное в Eclipse .