Java 我得到了ClassCastException,尽管我重写了compareTo()

Java 我得到了ClassCastException,尽管我重写了compareTo(),java,classcastexception,comparator,compareto,Java,Classcastexception,Comparator,Compareto,我收到ClassCastException错误。当我插入从我创建的类派生的对象时,会发生此错误。 我的代码如下: 当我运行时,我总是得到ClassCastException错误。 此外,我的类的比较器在调试器中显示为null 据我所知,我已经编写了一个比较器,并重写了必要的方法 如何将集合与已创建并使用contains方法的类一起使用 public class Person implements Comparable<Person> { int age; double

我收到ClassCastException错误。当我插入从我创建的类派生的对象时,会发生此错误。 我的代码如下: 当我运行时,我总是得到ClassCastException错误。 此外,我的类的比较器在调试器中显示为null

据我所知,我已经编写了一个比较器,并重写了必要的方法

如何将集合与已创建并使用contains方法的类一起使用

public class Person implements Comparable<Person>
{
    int age;
    double height;
    public Person(int age, double height)
    {
        this.age = age;
        this.height = height;
    }
    @Override
    public int compareTo(Person person) 
    {
        return age - person.age;
    }
    public boolean equals(Object obj)
    {
        final Person other = (Person) obj;
        if (this.age == other.age)
            return true;
        return false;
    }
    public static void main(String[] args)
    {
        Set<Person> people = new HashSet<>();
        Person p1 = new Person(10, 1.00);
        Person p2 = new Person(11, 1.10);
        Person p3 = new Person(12, 1.20);
        Person p4 = new Person(14, 1.40);
        people.add(p1);
        people.add(p2);
        people.add(p3);
        people.add(p4);
        if(people.contains(12))
            System.out.println("contains");
        else
            System.out.println("does not contain");
    }
}
我已设法消除了这个错误。但是现在,输出是不包含的。

我假设您的类基于代码实现了类似的接口。您的类包含一个名为getID的方法。因此,当您重写compareTo方法时,您需要确保对象比较是有意义的。我不确定你的getID返回了什么。但它似乎是整数。因此,您可能希望将compareTo的实现更改为:

@Override
public int compareTo(Adjacent adj) {

    return this.getId() - adj.getId();
}
因此,通过这种方式,比较将返回负/零/正,具体取决于两个相邻类对象的ID比较


同样在重写的equals方法中,实现是不正确的,因为两个对象不一定相等,即使它们具有相同的哈希代码。中给出了重写equals和hashCode方法的一个很好的示例。另外,在您的情况下,我认为您甚至不需要重写equals方法,因为您的类已经实现了可比较的接口。

不要使用不同类型的参数调用contains;这种行为实际上是错误的。出于遗留原因,contains方法是一种非泛型方法,如果您使用的是TreeSet,那么它是不安全的。如果您实现hashCode和equals并切换到HashSet,您的问题就会消失

你真的需要按年龄分类的人吗

编辑:我现在明白你想做什么了。你不需要一个集合,你需要地图,或者只是一个单一的循环来寻找给定的年龄

for (Person p : people) {
    if (p.age == 12) ...;
}


我要建议的与ClassCastException无关,抛出ClassCastException的原因很简单,因为您正在使用一组Person类型的对象上的int参数检查contains。。。简短回答:您不能将对象强制转换为它不是实例的子类。甚至

对于这种情况,我非常喜欢使用番石榴谓词。谓词允许您对任何iterable应用布尔条件,返回满足指定条件的元素。在您的示例中,您可以定义谓词来返回您想要的任何年龄的人的子集

Predicate<Person> getAgePredicate(final int age) {
    return new Predicate<Person>() {
        public boolean apply(Person p) { return p.age == age; }
    };
}


希望这能有所帮助。

您应该更改等于实现的内容,否则您将度过一段不愉快的时光……ClassCastException的确切位置是哪里?错误消息是什么?当我试图调用一个列表的contains方法时,我得到了ClassCastException,该列表中的所有对象都是相邻的。问题与最初编写的完全不同。你完全改变了问题的性质。你应该再发一条。这是个不错的问题。长话短说,不能在哈希集上调用containsint。你真的需要用一个人来包装它。contains将只检查标识字段,因此1.20不重要。标识字段是用于equals和hashcode的字段。所有这些都无助于ClassCastException。如果没有引发异常的实际代码,我无法判断原因。但是这些是我在文章中看到的问题可能来自的地方。不,这些问题不会引起ClassCastException。Stack Overflow允许我们在问题下发表评论的原因是,我们可以在发布答案之前询问所需的实际信息,而不是相反。我不需要对列表进行排序。我只是想看看是否有一个12岁的人,然后运行这个循环。如果你要做很多,你会想要地图。如果你需要12岁的人的名单,你需要第二个例子。我已经更新了这个问题。请检查。12岁的人与整数12不同。
Predicate<Person> getAgePredicate(final int age) {
    return new Predicate<Person>() {
        public boolean apply(Person p) { return p.age == age; }
    };
Set<Person> people = new Hashset<>();
... // populate people
Set<Person> peopleOfAgeTwelve = Sets.filter(people, getAgePredicate(12));