考虑以下 Kotlin 代码:
data class CachedUserData(var contracts: MutableList<String>) {
var localDateTime: LocalDateTime = LocalDateTime.now()
}
当我尝试通过自动生成的 getter 合约列表并从外部修改它时,我会抛出异常
java.lang.UnsupportedOperationException: null
。调查显示,在此类中,contracts
字段被初始化为类型ImmutableCollections$ListN
。
我可以通过添加以下数据修改功能来绕过这个问题:
fun addContract(item: String) {
val newList = mutableListOf(*contracts.toTypedArray());
newList.add(item);
contracts = newList;
}
然后,该类构造之后的类型是
ImmutableCollections$ListN
,但通过此函数调用进行修改后,该类型将更改为 ArrayList
并保持这种状态。
这个特定类的实例是作为网络资源获取(普通 Java
List
)的结果而创建的,随后通过流传递到某些过滤器,然后由 .toList()
Java 收集器收集。
我的问题是:
.getContracts().add(value);
构造?编辑: 该类在项目的某些 Java 部分中实例化,并提供
List<String>
类型作为输入参数:
提前非常感谢!
Java 没有额外的类型来区分可变列表和不可变列表。所有列表,无论是可变的还是不可变的,都由
java.util.List
类型表示。在 Kotlin 中, List
和 MutableList
都映射到 Java 中的 java.util.List
接口。请参阅映射表此处。
即使你说你的类的构造函数在 Kotlin 中应该采用
MutableList
,但就 Java 而言,构造函数采用 java.util.List
。因此,Java 中的代码可以向其传递可变列表和不可变列表。
Stream.toList
调用的结果传递给构造函数,这就是问题 - toList
旨在返回不可变列表:
返回的
不可修改;调用任何 mutator 方法总会导致List
被抛出。UnsupportedOperationException
您应该使用
Collectors.toCollection
来控制返回列表的类型,并传入 mutable 列表类型的供应商。
// e.g. replace .toList() with
.collect(Collectors.toCollection(ArrayList::new))
或者,您可以在
addContract
块中执行此操作,而不是在 init
中创建列表的可变副本:
data class CachedUserData(var contracts: MutableList<String>) {
init {
contracts = ArrayList(contracts)
}
}