You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@FindBy注解时List移除元素后大小仍为3的问题求助

为什么@FindBy注解的List移除元素后大小不变?

这是因为PageFactory生成的List是一个代理对象,而非普通的ArrayList,它的底层逻辑和你手动创建的List完全不同,这才导致了两种截然不同的行为:

1. PageFactory代理列表的特性

当你用@FindBy注解声明List<WebElement>时,PageFactory并不会立刻去DOM中查询元素并生成一个固定大小的集合。它会创建一个动态代理列表,每次你调用size()、get()这类方法时,代理都会重新执行一遍你的xpath表达式//th,去DOM中实时获取当前符合条件的元素数量和内容。

在你的代码里,columns.remove(i)只是临时移除了代理列表中的一个元素引用,但这个操作既不会改变DOM中的实际元素,也不会影响代理列表后续的查询逻辑。所以当你再次调用columns.size()时,它又重新查询了一遍DOM,发现还是3个<th>元素,自然返回大小为3。

2. 手动创建List的行为

如果是通过driver.findElements(By.xpath("//th"))手动获取的List,这是一个普通的ArrayList快照——它会在调用方法时一次性把DOM中符合条件的元素全部取出来,存储在内存里。后续你对这个List的移除操作,都是直接修改内存中的集合,不会再去DOM重新查询,所以集合大小会正确显示为2。

解决办法

方案1:将代理列表转为普通集合

在操作前,把PageFactory生成的代理列表转成普通ArrayList,这样就变成了固定的快照,后续操作都基于内存中的集合,不会再触发DOM查询:

public List<WebElement> getColumns() {
    // 转成普通ArrayList,脱离代理逻辑
    List<WebElement> actualColumns = new ArrayList<>(columns);
    System.out.println("Initial columns list size " + actualColumns.size());
    
    for (int i = 0; i < actualColumns.size(); i++) {
        System.out.println(actualColumns.get(i).getText());
        if (actualColumns.get(i).getText().equals("Instructor")) {
            actualColumns.remove(i);
            // 移除元素后要i--,避免跳过下一个元素
            i--;
        }
    }
    
    System.out.println("After modification column list size " + actualColumns.size());
    return actualColumns;
}

方案2:避免直接操作PageFactory生成的List

不要直接修改@FindBy注解的List对象,而是每次需要时手动执行查询,或者先转为普通集合再进行增删操作。

另外提醒一句:你代码里的循环移除元素逻辑有个小问题——移除元素后如果不执行i--,会导致循环跳过下一个元素,这个是Java集合操作的常见坑,注意规避~

内容的提问来源于stack exchange,提问作者Blue Star

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:12:46