ClassCastException: java.lang.Object cannot be cast to ...On an Inner class

1,454 views
Skip to first unread message

Omri Tavor

unread,
Jan 22, 2015, 4:01:06 AM1/22/15
to equalsv...@googlegroups.com
Hi,
I've started using your library for my projects and its really awesome!
I have encountered though an issue I can't seem to work around it.  
I have the following class:

class MyCollection<T> {
   protected final Map<T, Node<T>> map;
   protected Optional<Node<T>> head;
   protected Optional<Node<T>> last;
   .....
   .....
   .....
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (!head.isPresent() ? 0 : head.get().value.hashCode());
result = prime * result + (!last.isPresent() ? 0 : last.get().value.hashCode());
result = prime * result + ((map == null) ? 0 : map.keySet().hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyCollection<T> other = (MyCollection) obj;
if (head.isPresent()) {
if (!other.head.isPresent())
return false;
if (!head.get().value.equals(other.head.get().value))
return false;
} else if (other.head.isPresent())
return false;
if (last.isPresent()) {
if (!other.last.isPresent())
return false;
if (!last.get().value.equals(other.last.get().value))
return false;
} else if (other.last.isPresent())
return false;
if (!map.keySet().equals(other.map.keySet()))
return false;
return true;
}
   .....
   .....
   .....
   .....
   private static class Node<T> {
T value;
Optional<Node<T>> prev = Optional.empty();
Optional<Node<T>> next = Optional.empty();

public Node(T t) {
value = t;
}
                //Node doesn't implement hashcode() and equals() since it has to be unique
   }
}

When I tried testing "MyCollection" using "EqualsVerifier.forClass(MyCollection.class).usingGetClass().verify()" I got the following exception:
java.lang.AssertionError: java.lang.ClassCastException: java.lang.Object cannot be cast to com.example.MyCollection$Node

Do you have any idea how can I overcome this issue? I though about using withPrefabValues as you suggest in the FAQ but I'm unable to create Node<> instances which makes sense and in addition this class is private.

Jan Ouwens

unread,
Jan 22, 2015, 8:39:04 AM1/22/15
to equalsv...@googlegroups.com
Hi Omri,

Thanks for your message. I'm glad to hear you like EqualsVerifier.

I'm at work and don't have access to Java 8 right now, so I haven't been able to verify this, but I think your problem is basically the same as this issue:
You're right that withPrefabValues will help you, but I understand that this is not an option for you.

However, I think a better solution would be not to unwrap your Optionals all the time. If you read the Javadoc for Optional ( http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html ), you'll see that Optional.equals and Optional.hashCode already do what you're doing by hand here. In other words; instead of this:


if (last.isPresent()) {
if (!other.last.isPresent())
return false;
if (!last.get().value.equals(other.last.get().value))
return false;
}

You could write this:

if (!Objects.equals(last, other.last)) {
return false;
}

The same goes for the hashCode.

Apart from reducing the amount of code in your equals and hashCode methods, it will also ensure that EqualsVerifier doesn't get confused while unwrapping the Optional values, as explained in Issue 84. That issue talks about Lists, but the same applies for Optional or any other generic container.


Hope this helps!

Jan


--
You received this message because you are subscribed to the Google Groups "equalsverifier" group.
To unsubscribe from this group and stop receiving emails from it, send an email to equalsverifie...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Omri Tavor

unread,
Jan 26, 2015, 7:35:04 AM1/26/15
to equalsv...@googlegroups.com
Thanks, Jan. I will try it out and post the results.
Reply all
Reply to author
Forward
0 new messages