在使用GWT框架转换Applet时,我偶然发现了这段代码,其中作者在一个循环中查找数组imageNames的长度,直到发生越界异常。它可以在Applet中工作,但不能在GWT中工作!在GWT编译之后,浏览器循环并且不显示反应。用JavaScriptException替换Exception无济于事。
boolean error=false;
int n_img = -1;
String tmp;
String[] imageNames;
...
while (!error) {
try {
tmp = imageNames[(++n_img)];
} catch (Exception e) {
error = true;
}
}
您知道如何在GWT中捕获越界异常吗?
发布于 2018-05-19 20:32:54
这是GWT的“缺点”之一--在性能方面,没有添加额外的仿真来解决本应完全可以避免的bug。但这是最明显的例子之一。
首先,回想一下JS,不管是好是坏,在Array
s中为它可能没有空间的索引赋值是完全可以的-你可以用它来创建一个稀疏数组,跳过数组末尾很远的地方,你甚至可以给负索引赋值。
在Array
特性的基础上,实现了Java数组,它不是读取表达式array[n]
并重写它以在赋值之前根据长度检查n
(每次读取或写入都需要两次检查),而是保持原样。
而且,由于像这样的数组操作通常在循环中(例如在代码中),这种更改将使循环中的每一步都更快,因为作为循环条件的一部分进行边界检查是微不足道的。
而且,通常Java用户不会定期编写数组代码,而是依赖于ArrayList
或类似的东西-它确实会执行这些检查(尽管可以禁用或减少检查以提高运行时性能)。
这并不是很糟糕的另一个原因是:有时您希望用Java编写代码,并期望(这并不是没有道理的)您实际上是在对JS输出执行操作。这允许像这样的技巧:
array[array.length] = item;
使用每一项来增长数组。显然在JVM中会失败,但这是用JS编写的自然代码。
最后,除非我大错特错,否则这甚至不是编写该循环的一种非常优化的方法,即使抛出和捕获异常比仅仅在循环的每一步执行<
检查都要便宜-我们仍然在每一步检查!error
是否为真!相反,只要让循环永远运行,并实际退出它,而不是需要额外的布尔值来跟踪异常已经为您跟踪的内容:
// just like the code in the question, do not do this,
// this is just an example of how to get "too clever"
try {
while (true) {
tmp = imageNames[(++n_img)];
}
catch (Exception ignore) {
// do nothing, something "exceptional" but totally expected has occurred
}
发布于 2018-06-13 14:32:33
因此,感谢您的评论和解释答案。这将有助于我的进一步发展。现在,我这样更改了错误循环。
while (!error) {
try {
tmp = this.imageNames[(++n_img)];
error=(n_img==imageNames.length); // correct severe bug
} catch (Exception e) {
error = true;
}
}
https://stackoverflow.com/questions/50423326
复制相似问题