8

我正在使用装饰器模式List<WebElement>。这种装饰的一部分需要使用代理。

当我get(index)使用超出范围的索引调用时,它会引发IndexOutOfBounds异常,然后由代理捕获,并用UndeclaredThrowableException.

我的理解是,只有在检查异常 时才应该这样做。IndexOutOfBounds是一个未经检查的异常,那为什么要包装呢?

即使我添加throws IndexOutOfBounds到我的invoke函数中,它仍然会被包装。

这是我的代码:

@SuppressWarnings("unchecked")
public WebElementList findWebElementList(final By by){
    return new WebElementList(
            (List<WebElement>) Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    new Class<?>[] { List.class }, new InvocationHandler() {
        // Lazy initialized instance of WebElement
        private List<WebElement> webElements;

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if (webElements == null) {
                webElements = findElements(by);
            }
            return method.invoke(webElements, args);
        }
    }), driver);
}

这是我的堆栈跟踪的一部分:

java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy30.get(Unknown Source)
at org.lds.ldsp.enhancements.WebElementList.get(WebElementList.java:29)
...
Caused by: java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:604)
at java.util.ArrayList.get(ArrayList.java:382)
... 41 more
4

2 回答 2

8

维克·张是对的。您需要将调用包装在 try-catch 中并重新抛出内部异常。

try {
  return method.invoke(webElements, args);
} catch (InvocationTargetException ite) {
  throw ite.getCause();
}

原因是“Method.invoke”将那些在方法代码中抛出的异常包装在 InvocationTargetException 中。

java.lang.reflect.方法:

抛出:
...
InvocationTargetException - 如果底层方法抛出异常。

java.lang.reflect.InvocationTargetException:

InvocationTargetException 是一个已检查的异常,它包装了由调用的方法或构造函数抛出的异常。

代理对象的类没有在其“抛出”中声明 InvocationTargetException。这会导致 UndeclaredThrowableException。

于 2015-08-19T11:02:16.357 回答
3

我没有足够的声誉来发表评论。您的问题似乎与此非常相似

您可以在那里查看解决方案,看看是否可行。

简而言之,您需要将您的method.invokeinto try{}catch异常和throw它再次包装起来。

于 2013-11-22T05:07:39.783 回答