Ответ 1
Обязательно включите этот параметр для javac при компиляции ваших классов:
-g:lines,source,vars
Опция компилятора "-g" может использоваться для управления количеством отладочной информации, которая должна быть сгенерирована в файлы классов (см. документация)
Вот простой пример с lambdas:
package test;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestLambda {
public static Comparator<String> comparator1() {
return (o1, o2) -> {
return o1.compareTo(o2);
};
}
public static Comparator<String> comparator2() {
return (o1, o2) -> {
System.out.println("test");
if (true) {
throw new RuntimeException("Exception"); // line 20: stacktrace points to this line
}
return o1.compareTo(o2);
};
}
public static void main(String[] args) {
List<String> strings = Arrays.asList("string1", "string2", "string3");
Collections.sort(strings, comparator2());
}
}
Вот стек:
Exception in thread "main" java.lang.RuntimeException: Exception
at test.TestLambda.lambda$comparator2$1(TestLambda.java:20)
at test.TestLambda$$Lambda$1/189568618.compare(Unknown Source)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:351)
at java.util.TimSort.sort(TimSort.java:216)
at java.util.Arrays.sort(Arrays.java:1438)
at java.util.Arrays$ArrayList.sort(Arrays.java:3895)
at java.util.Collections.sort(Collections.java:175)
at test.TestLambda.main(TestLambda.java:29)
Как вы видите, stacktrace at test.TestLambda.lambda$comparator2$1(TestLambda.java:20)
указывает на точную строку исходного кода.
В вашей среде IDE должна быть возможность проанализировать stacktrace и украсить ее ссылками, которые нажимают на которые должны привести вас к точной строке в ваших источниках (по крайней мере, то, что делает IntelliJ IDEA).
Если вы скомпилируете с помощью -g:none
, stacktrace будет отличаться:
Exception in thread "main" java.lang.RuntimeException: Exception
at test.TestLambda.lambda$comparator2$1(Unknown Source)
at test.TestLambda$$Lambda$1/189568618.compare(Unknown Source)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:351)
at java.util.TimSort.sort(TimSort.java:216)
at java.util.Arrays.sort(Arrays.java:1438)
at java.util.Arrays$ArrayList.sort(Arrays.java:3895)
at java.util.Collections.sort(Collections.java:175)
at test.TestLambda.main(Unknown Source)
Update:
Ниже приведен еще один пример, который ближе к заданному в вопросе:
package test;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TestLambda {
public static Comparator<String> comparator1() {
return (o1, o2) -> {
return o1.compareTo(o2);
};
}
public static Comparator<String> comparator2() {
return (o1, o2) -> {
System.out.println("test");
if (true) {
throw new RuntimeException("Exception");
}
return o1.compareTo(o2);
};
}
public static void main(String[] args) {
List strings = Arrays.asList(1, 2, 3);
Collections.sort(strings, comparator2());
}
}
Единственное различие заключается в том, что он использует исходный тип для списка, что позволяет использовать компаратор String
для списка Integers
. Столбец на самом деле не содержит номера строк, поскольку исключение произошло во время кастинга, а не в нашем исходном коде:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
at test.TestLambda$$Lambda$1/189568618.compare(Unknown Source)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:351)
at java.util.TimSort.sort(TimSort.java:216)
at java.util.Arrays.sort(Arrays.java:1438)
at java.util.Arrays$ArrayList.sort(Arrays.java:3895)
at java.util.Collections.sort(Collections.java:175)
at test.TestLambda.main(TestLambda.java:29)
Основное правило здесь - не использовать необработанные типы, которые в этом случае упростят процесс отладки (Что такое необработанный тип и почему мы не должны его использовать?). Компилятор также может помочь вам здесь: включить этот параметр для javac:
-Xlint:all
Компилятор будет предупреждать вас о сырых типах множеством других вещей. Добавьте еще один вариант:
-Werror
и компилятор выдаст ошибку вместо предупреждения (полезно при использовании с серверами CI для обеспечения высокого качества исходного кода)