Java运行时报ClassCastException:LibroConcreto无法转换为java.lang.Comparable
问题根因
你在Catalogo类的无参构造方法中使用了**无参构造的TreeSet**作为内部存储容器:
public Catalogo () { libri=new TreeSet <> (); // 无参TreeSet要求元素实现Comparable接口 // 其余逻辑省略 }
无参构造的TreeSet底层会默认要求存储的元素实现java.lang.Comparable接口,用于插入时排序。但你的Libro抽象类和LibroConcreto实现类都没有实现该接口,所以调用add方法插入元素时会抛出类型转换异常。
解决方案
你本身的需求是仅在返回副本时按指定规则排序,内部存储不需要排序,所以优先推荐方案1:
方案1:更换内部存储结构(最符合需求)
把内部存储的TreeSet换成不需要排序的HashSet/ArrayList即可,完全不需要修改其余排序逻辑:
修改Catalogo类的属性声明和构造方法:
// 把Set<T> libri的实现类从TreeSet换成HashSet private Set<T> libri; public Catalogo () { libri=new HashSet<>(); // 替换为HashSet,不需要元素实现Comparable numeroCataloghi++; codice=numeroCataloghi; numLibri=0; }
方案2:保留TreeSet作为内部存储
如果你确实需要内部存储本身维持排序状态,可以二选一:
- 给内部TreeSet传入默认比较器
修改构造方法中libri的初始化逻辑,传入你已经写好的任意一个比较器即可:
public Catalogo () { // 比如默认按标题排序,传入LibriByTitolo比较器 libri=new TreeSet<>(new LibriByTitolo()); // 其余逻辑省略 }
- 让Libro类实现Comparable接口
给抽象父类Libro添加默认比较规则,所有子类自动继承:
public abstract class Libro implements Comparable<Libro>{ // 原有属性和方法省略 @Override public int compareTo(Libro o) { // 自定义默认排序规则,比如按标题排序 return this.getTitolo().compareToIgnoreCase(o.getTitolo()); } }
额外注意点
你的测试代码TestProgramma里有逻辑错误,获取按标题排序的集合时调用了错误的方法:
// 原错误代码,两次都调用了按年份排序的方法 Set <LibroConcreto> c1OrdinatoByTitolo=c1.leggiLibriByAnno(); // 修改为 Set <LibroConcreto> c1OrdinatoByTitolo=c1.leggiLibriByTitolo();
内容的提问来源于stack exchange,提问作者Lorenzo Bucci
相关产品推荐
相关产品推荐

