Java操作DownloadRequest的headers集合抛出UnsupportedOperationException排查
异常根因定位
java.lang.UnsupportedOperationException触发原因:代码直接将downloadRequest.getHeaders()返回的集合引用赋值给headers字段,而该返回集合本身为不支持结构修改操作的特殊实现,常见类型包括Arrays.asList()生成的内部类java.util.Arrays$ArrayList、JDK不可变集合、框架包装的只读集合。这类集合未实现clear()、add()、remove()等方法的修改逻辑,调用时会直接抛出不支持操作异常。java.lang.ClassCastException触发原因:java.util.Arrays$ArrayList与日常使用的java.util.ArrayList是两个完全独立、无继承关系的类,仅类名相似。将特殊实现集合强转为java.util.ArrayList时,因类无兼容关系必然抛出类转换异常。- 原代码逻辑缺陷:三元判断仅在原headers为null时创建了可修改的
ArrayList,原headers非空时直接透传了不可修改的原集合引用,从根源上未持有可自由操作的集合实例。
落地方案
- 摒弃对返回集合做强转的思路,无论原集合是什么实现,都主动创建一个完全可控的、支持全量集合操作的
java.util.ArrayList实例,将原集合元素全部拷贝到新实例中作为headers的初始值。 - 修正原代码隐蔽问题:原代码中的
myConfig方法名与类名MyClass大小写不一致,在Java语法中不属于构造方法,实例化类时不会自动执行该初始化逻辑,需将方法名修正为与类名完全一致的构造方法。 - 调整后代码参考:
@Getter public class MyClass { // 明确指定为ArrayList类型,保证所有增删改查操作可用 private final List<String> headers; // 构造方法与类名保持完全一致 public MyClass(DownloadRequest downloadRequest) { Collection<String> originHeaders = downloadRequest.getHeaders(); // 新建ArrayList拷贝所有元素,持有完全可控的可修改集合 this.headers = originHeaders == null ? new ArrayList<>() : new ArrayList<>(originHeaders); } }
- 方案适配性:
- 无类型强转逻辑,从根源杜绝类转换异常
- 新建的
ArrayList实例完全由当前类持有,所有结构修改操作均有完整实现,调用clear()等方法时不会抛出不支持操作异常 - 对原集合的实现类型无感知,可兼容任意类型的Collection返回值,无需关注原集合的具体实现
内容的提问来源于stack exchange,提问作者Akshay Hazari
相关产品推荐
相关产品推荐

