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

如何在Dart/Flutter中修改复制列表元素且不影响原列表?

Dart中列表拷贝与对象引用的常见误区

你遇到的问题本质是对Dart中对象引用和列表拷贝机制的误解,核心点如下:

问题原因

Dart的列表存储的是对象的引用,而非对象本身。你用List.from(friends)做的是浅拷贝——它只是把friends列表里的引用复制到templist中,并没有创建新的User对象。这意味着:

  • users[0]、friends[0]、templist[0]指向的是同一个User实例
  • 修改任意一个列表中对象的name属性,所有指向该实例的变量都会同步看到变化

看你代码的执行流程:

  1. final u1 = users[0]是把users列表第一个元素的引用赋值给u1,添加到friends后修改friends[0].name,本质就是修改users[0]的name
  2. templist = List.from(friends)只是复制了friends里的两个引用,所以修改templist[0].name时,users[0]和friends[0]的name也会跟着变

解决方案:深拷贝对象

要实现修改新列表元素不影响原列表,需要为每个User对象创建新实例(深拷贝),而不是复制引用。

步骤1:给User类添加拷贝方法

class User {
  String name;
  String age;
  User({required this.name, required this.age});
  
  // 拷贝构造方法,用于创建新的User实例
  User.copy(User other) : name = other.name, age = other.age;
}

步骤2:复制列表时创建新对象

把原来的templist = List.from(friends)替换为:

templist = friends.map((user) => User.copy(user)).toList();

或者直接通过构造函数创建新实例:

templist = friends.map((user) => User(name: user.name, age: user.age)).toList();

修改后的完整代码

class User {
  String name;
  String age;
  User({required this.name, required this.age});
  
  User.copy(User other) : name = other.name, age = other.age;
}

void main() {
  List<User> users = [
    User(name: 'A', age: '43'),
    User(name: 'B', age: '12'),
    User(name: 'C', age: '53'),
    User(name: 'D', age: '22'),
  ];

  List<User> friends = [];
  List<User> templist = [];

  final u1 = users[0];
  friends.add(u1);
  friends[0].name = 'AA';
  final p2 = users[1];
  friends.add(p2);
  friends[1].name = "BB";

  // 深拷贝创建新的User实例
  templist = friends.map((user) => User.copy(user)).toList();

  templist[0].name = "AAA";
  templist[1].name = "BBB";

  print("users = ${users.map((u) => u.name).toList()}");
  print("friends = ${friends.map((f) => f.name).toList()}");
  print("templist = ${templist.map((t) => t.name).toList()}");
}

运行结果

users = [A, B, C, D]
friends = [AA, BB]
templist = [AAA, BBB]

补充说明Dart的传值/传引用

Dart中所有变量传递都是传值,但对于对象类型,这个"值"是对象在内存中的引用地址。所以:

  • 当你把对象赋值给另一个变量,或者添加到列表,传递的是引用的副本,指向同一个对象
  • 基本类型(int、String、bool等)是不可变的,修改时会创建新实例,因此不会出现这种引用同步的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:00:10