Ton*_*ony 17 java lambda exception
假设我有一个ComparatorFactory,它有许多由lambda组成的比较器:
public static Comparator<SomeClass> getXCmp() {
return (o1, o2) -> {
Double d1 = Double.parseDouble(o1.getX());
Double d2 = Double.parseDouble(o2.getX());
return d1.compareTo(d2);
};
}
Run Code Online (Sandbox Code Playgroud)
我使用这些比较器对数据进行排序和过滤.不幸的是,我在某个地方使用了错误的比较器,它导致ClassCastException如下所示:
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
at businesslogic.utility.ComparatorFactory$$Lambda$24/115669291.compare(Unknown Source)
at javax.swing.DefaultRowSorter.compare(DefaultRowSorter.java:968)
...
...
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它显示了(Unknown Source)哪些使我很难找到哪个比较器出错.我也试着比较发生之前(即,在上面的示例,在添加断点DefaulRowSorter.java:968),但next step也无法找到它是拉姆达(它跳到错误的比较:在没有做double和string,当我终于找到了它不是正确的错误).
在我发现错误之后(通过尝试理解整个项目和很多时间),我尝试了一个匿名类.堆栈的回溯明确地告诉我它在哪里.
如果我希望lambda提供简洁的代码,有没有什么好方法可以找到lambda源的位置或者在发生异常时帮助我的任何好的做法?
一个简单的例子来重新产生类似的问题.
在编译类时,请确保为javac包含此选项:
-g:lines,source,vars
Run Code Online (Sandbox Code Playgroud)
"-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());
}
}
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪:
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)
Run Code Online (Sandbox Code Playgroud)
如您所见,stacktrace at test.TestLambda.lambda$comparator2$1(TestLambda.java:20)指向源代码的确切行.
您的IDE应该能够解析堆栈跟踪并使用链接进行装饰,点击链接可以将您带到源中的确切行(至少这是IntelliJ IDEA所做的).
如果使用-g:nonestacktrace进行编译则会有所不同:
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)
Run Code Online (Sandbox Code Playgroud)
更新:
下面是另一个更接近问题中提供的示例:
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());
}
}
Run Code Online (Sandbox Code Playgroud)
唯一的区别是它使用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)
Run Code Online (Sandbox Code Playgroud)
这里的经验法则是不使用原始类型,在这种情况下,这将使调试过程更容易(什么是原始类型,为什么我们不应该使用它?).编译器也可以在这里帮助你:为javac包含这个选项:
-Xlint:all
Run Code Online (Sandbox Code Playgroud)
编译器会警告你关于原始类型的许多其他事情.添加其他选项:
-Werror
Run Code Online (Sandbox Code Playgroud)
并且编译器将产生错误而不是警告(当与CI服务器一起使用以确保高质量的源代码时非常有用)
| 归档时间: |
|
| 查看次数: |
1514 次 |
| 最近记录: |