Bob*_*out 54 java exception try-catch comparator
由于最近存储在数据库中的数据不好,导致程序崩溃.这让我感到困惑,因为我觉得我有一个阻止这一点.
以下代码的目的是比较员工徽章编号并对其进行排序.如果出现错误,请返回-1并且士兵开启 - 请勿停止,因为数千个徽章编号中的一个错误:
public int compare(Employee t, Employee t1) {
Integer returnValue = -1;
try {
Integer tb = Integer.parseInt(t.getBadgeNumber());
Integer t1b = Integer.parseInt(t1.getBadgeNumber());
returnValue = tb.compareTo(t1b);
} catch (Exception e) {
returnValue = -1;//useless statement, I know.
}
return returnValue;
}
Run Code Online (Sandbox Code Playgroud)
当坏徽章编号被击中时(在这种情况下为t),我得到了一个"java.lang.IllegalArgumentException:比较方法违反了它的一般合同!" 错误而不是在catch中返回-1.
关于这里的捕获,我不明白什么?
完整的堆栈跟踪:
16-May-2018 14:28:53.496 SEVERE [http-nio-8084-exec-601] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [RequestServlet] in context with path [/AppearanceRequest] threw exception
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
at java.util.TimSort.sort(TimSort.java:223)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at org.bcso.com.appearancerequest.html.NotifierHTML.getHTML(NotifierHTML.java:363)
at org.bcso.com.appearancerequest.AppearanceRequestServlet.processRequest(AppearanceRequestServlet.java:96)
at org.bcso.com.appearancerequest.AppearanceRequestServlet.doGet(AppearanceRequestServlet.java:565)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:301)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:74)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1015)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:652)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1575)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1533)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)
调用代码:
List<Employee> employeeList = DatabaseUtil.getEmployees();
Collections.sort(employeeList, new BadgeComparator());
Run Code Online (Sandbox Code Playgroud)
rge*_*man 144
异常(无论是什么)被抓住了catch (Exception e)
.您没有记录此异常,因此您不知道它是什么.你应该以某种方式记录它,以便你知道到底发生了什么.
返回时会出现问题-1
.这允许Java的当前排序算法有时会捕获的顺序不一致的可能性.总之,返回-1
上的错误意味着你在断言都a < b
和b < a
真实,因为异常会在两种情况下被抓住.这在逻辑上是不正确的.排序算法检测到这个并抛出IllegalArgumentException
.请注意,该compare
方法不在堆栈跟踪中; 这是对的呼唤Collections.sort
.
除了记录异常之外,在进入程序中的比较步骤之前处理它.如果必须将字符串解析为整数,请在创建Employee
对象时执行此操作,以便在进入程序中的排序步骤之前进行验证.A Comparator
不应该验证数据; 它应该只比较数据.
Zab*_*uza 53
java.lang.IllegalArgumentException:比较方法违反了它的一般合同!
你的内心不会抛出异常try
.这就是它没有被抓住的原因.例外情况来自NotifierHTML.java:363
您调用Collection#sort
哪个TimSort
类使用的代码.然后TimSort.java:868
由该TimSort#mergeHi
方法抛出异常.
它告诉您,您的Comparator#compare
方法实现是错误的.如其文档中所述,它违反了合同:
比较它的两个参数的顺序.返回负整数,零或正整数,因为第一个参数小于,等于或大于第二个参数.
实施者必须确保
sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
所有x
和y
.(这意味着x.compareTo(y)
必须抛出异常iffy.compareTo(x)
抛出异常.)实现者还必须确保关系是可传递的:
(x.compareTo(y) > 0 && y.compareTo(z) > 0)
暗示x.compareTo(z) > 0
.最后,实现者必须确保这
x.compareTo(y) == 0
意味着sgn(x.compareTo(z)) == sgn(y.compareTo(z))
对所有人而言z
.
您的实施违反了其中一项要求,并且检测到了该方法.
问题是-1
如果发生错误则返回.假设你有两个值first
和second
.并且至少其中一个会引发异常.
所以,如果你想比较first
有second
,你会得到-1
:
compare(first, second) -> -1
Run Code Online (Sandbox Code Playgroud)
这意味着first
是小比second
.但是,如果你将它与你得到的另一种方式进行比较-1
:
compare(second, first) -> -1
Run Code Online (Sandbox Code Playgroud)
因为两种变体都会引发异常,这会导致您的异常return -1;
.但这意味着你的compare
方法说:
first < second
second < first
Run Code Online (Sandbox Code Playgroud)
两者同时存在,这在逻辑上是不正确的,违反了合同.
您需要正确定义订购中不可分类内容的位置.例如,让我们定义它总是小于任何数字.所以我们想要
text < number
Run Code Online (Sandbox Code Playgroud)
如果两者都是不可解决的,我们该怎么办?我们可以说它们是平等的,我们可以比较它们的词典.让我们保持简单,并说任何两个文本被认为是平等的:
text = text
Run Code Online (Sandbox Code Playgroud)
我们通过检查哪些参数是不可解析的然后返回正确的值来实现它:
@Override
public int compare(Employee first, Employee second) {
Integer firstValue;
Integer secondValue;
try {
firstValue = Integer.parseInt(first.getBadgeNumber());
} catch (NumberFormatException e) {
// Could not parse, set null as indicator
firstValue = null;
}
try {
secondValue = Integer.parseInt(second.getBadgeNumber());
} catch (NumberFormatException e) {
// Could not parse, set null as indicator
secondValue = null;
}
if (firstValue == null && secondValue != null) {
// text < number
return -1;
}
if (firstValue != null && secondValue == null) {
// number > text
return 1;
}
if (firstValue == null && secondValue == null) {
// text = text
return 0;
}
// Both are numbers
return Integer.compare(firstValue, secondValue);
}
Run Code Online (Sandbox Code Playgroud)
正如评论中暗示的那样,您可以Comparator
通过以下语句替换整个自定义类,该语句生成相同的Comparator:
Comparator<Employee> comp = Comparator.nullsLast(
Comparator.comparing(e -> tryParseInteger(e.getBadgeNumber())));
Run Code Online (Sandbox Code Playgroud)
与这样的tryParseInteger
方法一起:
public static Integer tryParseInteger(String text) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13995 次 |
最近记录: |