必须实现 compareTo() 方法并正确声明泛型,否则 Collections.sort()、TreeSet 等会抛 ClassCastException;需做类型检查、null 处理、避免溢出、多字段短路比较,并确保与 equals() 逻辑一致。

必须实现 compareTo() 方法,否则 Collections.sort()、TreeSet 等会直接抛 ClassCastException。
泛型参数必须写对:用 Comparable<user></user>,不是 Comparable<object></object> 或裸类型
声明 class User implements Comparable<user></user> 是硬性要求。写成 Comparable<object></object> 编译能过,但运行时 TreeSet<user></user> 无法识别排序契约——插入可能失败,或排序结果错乱。IDE 自动补全有时会出错,尤其在泛型类(如 Result<t></t>)里,更要手动核对 compareTo(User o) 的参数类型是否仍可静态确定,避免类型擦除后逻辑失效。
compareTo() 里必须做类型检查和 null 处理
常见崩溃就发生在没加 instanceof 判断或没处理 null 参数:
- 传入非本类实例(比如
new TreeSet().add(new Object())),不判o instanceof User就强转,立刻抛ClassCastException - 传入
null,不提前 throwNullPointerException,后续字段访问直接 NPE - 字段本身可能为
null(如String name),直接调name.compareTo()会崩,得用Objects.compare(name, o.name, String::compareTo)或先判空
别用减法算数值字段,优先用 Integer.compare() 等工具方法
写 this.age - o.age 看似简洁,但 age 是 int 时,若一正一负且绝对值很大(比如 2000000000 - (-2000000000)),整数溢出会翻转符号,导致“大于”变“小于”。正确做法是:
Integer.compare(this.age, o.age)Long.compare(this.timestamp, o.timestamp)Boolean.compare(this.active, o.active)- 字符串用
Objects.compare(str1, str2, String::compareTo),别用==或自己写空安全逻辑
多字段排序要用短路链式比较,别拼接字符串或乘权重
比如“先按状态升序,状态相同时按创建时间降序”,不能写 this.status + "-" + this.createdAt 去比——字符串拼接既慢又易错(时区、格式、null)。正确姿势是:
- 第一字段不等,直接 return 结果;只有相等,才继续比第二字段
- 升序用
this.field.compareTo(o.field),降序用o.field.compareTo(this.field) - 推荐组合:用
Comparator.comparing(User::getStatus).thenComparing(User::getCreatedAt, Comparator.reverseOrder())构造比较器,再在compareTo()里调它的compare(this, o)方法,语义清晰还不易漏 return
最容易被忽略的是:compareTo() 必须与 equals() 保持逻辑一致。如果 a.equals(b) 返回 true,那 a.compareTo(b) 就必须返回 0;否则往 TreeSet 里加两个“内容相同但 compareTo == 0”的对象,第二个会静默失败——集合认为它已存在。

















