可以,但需重写equals()和hashcode()以确保contains()等方法正常工作;treeset/treemap需实现comparable或传入comparator;序列化问题通常源于getter缺失、无参构造函数缺失或字段命名不规范。

自定义对象能直接放进 ArrayList 吗?
可以,但必须确保对象具备基本的“可存性”:即类已正确定义,且没有违反集合底层要求。Java 集合(如 ArrayList、HashSet)本身不限制元素类型,但实际使用中会暴露两类关键问题:NullPointerException(因字段未初始化)、以及逻辑错误(如 contains 或 remove 失效)。根本原因往往不是“能不能放”,而是“放进去后能不能正确识别和比较”。
为什么 contains() 找不到已添加的对象?
因为默认的 equals() 和 hashCode() 继承自 Object,只比较引用地址。即使两个对象字段值完全一样,只要不是同一个实例,contains() 就返回 false。
解决方法是重写这两个方法:
-
equals()要用instanceof判类型,逐个比较有意义的字段(注意null安全,推荐用Objects.equals(a, b)) -
hashCode()必须与equals()保持一致:相等的对象必须有相同哈希值;建议用Objects.hash(field1, field2)生成 - 如果用 Lombok,加
@EqualsAndHashCode注解即可,但需确认它包含的字段符合业务语义(例如不把临时计算字段或数据库 ID 加进去)
TreeSet 或 TreeMap 存自定义对象报 ClassCastException 怎么办?
这类集合依赖自然序(Comparable)或外部比较器(Comparator),不会调用 equals()。错误通常出现在:对象没实现 Comparable,或实现时用了错误类型(比如 compareTo(Object o) 里强制转成子类却传入了父类)。
立即学习“Java免费学习笔记(深入)”;
两种修复路径:
- 让类实现
Comparable<yourclass></yourclass>,并在compareTo()中用Integer.compare(this.id, other.id)等安全方式比较字段 - 构造集合时显式传入
Comparator,例如:new TreeSet((a, b) -> Integer.compare(a.getAge(), b.getAge())) - 注意:若同时用了
Comparable和自定义Comparator,后者优先;但别在两者中混用不同排序逻辑,否则contains()行为不可预测
序列化或 JSON 转换时字段丢失或报错?
这和集合存储无关,但常被一起遇到——尤其用 ArrayList<person></person> 存对象后转 JSON,结果只有空 {} 或抛 JsonMappingException。
常见原因和对策:
- 字段是
private但没提供 public getter(Jackson 默认只序列化 getter 方法暴露的属性) - 类没无参构造函数(Jackson 反序列化需要)
- 用了 Lombok 的
@Data却忘了@NoArgsConstructor(尤其当存在全参构造时,Lombok 不再自动生成无参构造) - 字段名含下划线或大小写不规范,而 JSON 库默认开启驼峰映射(如
user_name→userName),可配@JsonProperty("user_name")强制指定
真正麻烦的是“对象能存进集合、也能打印出来,但一转 JSON 就崩”,这时候得盯紧 getter 和构造函数,而不是怀疑集合本身。








