jira.codehaus.org

  • Log In Access more options
    • Online Help
    • Keyboard Shortcuts
    • About JIRA
    • JIRA Credits
    • What?s New
  • Dashboards Access more options (Alt+d)
  • Projects Access more options (Alt+p)
  • Issues Access more options (Alt+i)
  • groovy
  • GROOVY-4046

1 == new Object() throws ClassCastException

  • Log In
  • Views
    • XML
    • Word
    • Printable

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Critical Critical
  • Resolution: Fixed
  • Affects Version/s: 1.7.0
  • Fix Version/s: 1.6.8, 1.7.1, 1.8-beta-1
  • Component/s: None
  • Labels:
    None
  • Environment:
    tested for 1.7.0 and 1.6.0
  • Testcase included:
    yes

Description

Example 1:

assertFalse(new Object() == 1) // this is ok
assertFalse(1 == new Object()) // this throws a ClassCastException, because Groovy redirects the call to java.lang.Integer.compareTo(Integer i)

Example 2:

enum MyEnum { A, B, C }

assertFalse(new Object() == MyEnum.A) // this is ok
assertFalse(MyEnum.A == new Object()) // this throws a ClassCastException, because Groovy redirects the call to java.lang.Enum.compareTo(E e) where E extends java.lang.Enum<E>

Activity

Ascending order - Click to sort in descending order
  • All
  • Comments
  • Work Log
  • History
  • Activity
Hide
Permalink
Roshan Dawrani added a comment - 10/Feb/10 1:23 PM

In the corner case of a Comparable instance being comparedTo an Object instance, the comparison made by DefaultTypeTransformation#compareToWithEqualityCheck() was becoming Object.isAssignableFrom(SomeComparableClass), which was not really serving any purpose, because all classes are assignable to Object. This meaningless condition was causing the issue in both the reported scenarios and has been fixed now.

Show
Roshan Dawrani added a comment - 10/Feb/10 1:23 PM In the corner case of a Comparable instance being comparedTo an Object instance, the comparison made by DefaultTypeTransformation#compareToWithEqualityCheck() was becoming Object.isAssignableFrom(SomeComparableClass), which was not really serving any purpose, because all classes are assignable to Object. This meaningless condition was causing the issue in both the reported scenarios and has been fixed now.
Hide
Permalink
Peter Niederwieser added a comment - 06/Jul/10 4:55 PM

There seems to be a broader issue here: DefaultTypeTransformation.compareToWithEqualityCheck() assumes that instances of assignment-compatible classes are comparable. I don't think this assumption is safe, even for classes that obey the Comparable contract. For example:

class Foo implements Comparable<Foo> {
  int compareTo(Object other) {
    if (other.getClass() != Foo.class) throw new ClassCastException()
    0
  }
  
  boolean equals(Object other) {
      other.getClass() == Foo.class  
  }
}

class Bar extends Foo implements Comparable<Bar> {
  int compareTo(Object other) {
    if (other.getClass() != Bar.class) throw new ClassCastException()
    0
  }
  
  boolean equals(Object other) {
    other.getClass() == Bar.class  
  }
}

new Foo() == new Bar() // ClassCastException!
Show
Peter Niederwieser added a comment - 06/Jul/10 4:55 PM There seems to be a broader issue here: DefaultTypeTransformation.compareToWithEqualityCheck() assumes that instances of assignment-compatible classes are comparable. I don't think this assumption is safe, even for classes that obey the Comparable contract. For example:
class Foo implements Comparable<Foo> {
  int compareTo(Object other) {
    if (other.getClass() != Foo.class) throw new ClassCastException()
    0
  }
  
  boolean equals(Object other) {
      other.getClass() == Foo.class  
  }
}

class Bar extends Foo implements Comparable<Bar> {
  int compareTo(Object other) {
    if (other.getClass() != Bar.class) throw new ClassCastException()
    0
  }
  
  boolean equals(Object other) {
    other.getClass() == Bar.class  
  }
}

new Foo() == new Bar() // ClassCastException!
Hide
Permalink
Edward Sumerfield added a comment - 06/Feb/11 3:36 PM

A potential ramification of this change is this failing test when the equals and Comparable interface exist in the same class.

// Groovy 1.8 b4
class EqualsCompareTest extends GroovyTestCase {

void test_equals_along() { assert new EqualsOnly() == 1 }

void test_equals_and_compare() { assert new EqualsAndCompare() == 1 }
}

class EqualsOnly {
boolean equals(value) { 1 == value }
}

class EqualsAndCompare implements Comparable {
boolean equals(value) { 1 == value } }
int compareTo(value) { 1.compareTo(value) }
}

Show
Edward Sumerfield added a comment - 06/Feb/11 3:36 PM A potential ramification of this change is this failing test when the equals and Comparable interface exist in the same class. // Groovy 1.8 b4 class EqualsCompareTest extends GroovyTestCase { void test_equals_along() { assert new EqualsOnly() == 1 } void test_equals_and_compare() { assert new EqualsAndCompare() == 1 } } class EqualsOnly { boolean equals(value) { 1 == value } } class EqualsAndCompare implements Comparable { boolean equals(value) { 1 == value } } int compareTo(value) { 1.compareTo(value) } }

People

  • Assignee:
    Roshan Dawrani
    Reporter:
    Armin Weisser
Vote (1)
Watch (0)

Dates

  • Created:
    10/Feb/10 8:05 AM
    Updated:
    06/Feb/11 3:36 PM
    Resolved:
    10/Feb/10 1:23 PM
  • Atlassian JIRA (v5.0.4#731-sha1:3aa7374)
  • Report a problem
  • Powered by a free Atlassian JIRA open source license for Codehaus. Try JIRA - bug tracking software for your team.