确保在编译类时为 javac 包含此选项:
-g:lines,source,vars
“-g”编译器选项可用于控制应在类文件中生成多少调试信息(请参阅文档)
下面是一个 lambda 的简单示例:
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)
如您所见,堆栈跟踪指向源代码的确切行。at test.TestLambda.lambda$comparator2$1(TestLambda.java:20)
你的IDE应该能够解析堆栈跟踪,并用链接点击来修饰它,这应该会把你带到源代码中的确切行(至少这是IntelliJ IDEA所做的)。
如果使用堆栈编译,则堆栈跟踪将有所不同:-g:none
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)
更新:
下面是另一个更接近问题中提供的示例:
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());
}
}
唯一的区别是它对 List 使用原始类型,因此可以将比较器用于 列表。堆栈跟踪确实不包含行号,因为异常发生在转换过程中,而不是在我们的源代码中: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服务器一起使用时很有用,以确保源代码的高质量)