You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Samuel Fleischle <sf...@key-software.com> on 2007/09/11 14:42:23 UTC

[lang] ClassCastException in Enum.compareTo

Hi,
I updated from Commons Lang 2.1 to Commons Lang 2.3 and got some issues with the changed compareTo() method of Enum.
 
Here is my simplified Enum:
 
public class ItemStatus extends Enum {
 
      public static final ItemStatus CANCEL = new ItemStatus("CANCEL");
public static final ItemStatus SHIPPED = new ItemStatus("SHIPPED");
      public static final ItemStatus MOVED = new ItemStatus("MOVED");
 
/** Contains each status. */
      private static Set statuses;
 
// -------------------------------------------------------- Constructors
 
      protected ItemStatus(String name) {
            super(name);
            System.out.println(this.getClass().getName());
            buildStatusSet();
      }
 
      // -------------------------------------------------------- Static Methods
 
      /**
       * Returns the item status enumeration object for the given status name.
       * 
       * @param itemStatus
       *            name of the item status
       * @return the enumeration object, or <code>null</code> if it does not
       *         exist
       */
      public static ItemStatus valueOf(String itemStatus) {
            return (ItemStatus) getEnum(ItemStatus.class, itemStatus);
      }
 
      // -------------------------------------------------------- Public Methods
 
      /**
       * {@inheritDoc}
       */
      // @Override
      public final Class getEnumClass() {
            return ItemStatus.class;
      }
 
      /**
       * Gets all defined ItemStatus.
       * 
       * @return the enum object List
       * @see org.apache.commons.lang.enums.Enum#getEnumList(Class)
       */
      public static List getEnumList() {
            return getEnumList(ItemStatus.class);
      }
 
      // -------------------------------------------------------- Private Methods
 
      /**
       * Adds the status name to a Set of status names.
       */
      private void buildStatusSet() {
            if (statuses == null) {
                  statuses = new TreeSet();
            }
            statuses.add(this);
      }
}
 
And I got the ClassCastExcetion in the private "buildStatusSet()-Method if I try to add the status to the TreeSet. The TreeSet calls the compareTo-Method of the Enum. In Commons Lang 2.2 this method was changed with an additional comparison of the classes.
In my constructor I added a System.out.println of the instantiated classes and got the following output:
 
com.myapp.common.model.order.ItemStatus$1
com.myapp.common.model.order.ItemStatus$2
com.myapp.common.model.order.ItemStatus$3
 
The compareTo-Method now tries to compare ItemStatus$1 with ItemStatus$2 and says to me, that my ItemStatus-Enums are different classes.
 
I saw in JIRA there are some other issues in ValuedEnum.compareTo(). Is there a bug in the Enum.compareTo() implementation which got changed in Lang 2.2?
 
Thanks in advance for any help or comment on this issue.
 
Regards,
Sam

RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Posted by Jörg Schaible <Jo...@Elsag-Solutions.com>.
Samuel Fleischle wrote on Friday, September 14, 2007 9:19 AM:

> Hi Jörg,
> 
> thanks for your quick response and your approach to solve
> this issue. But anyway I think it should be possible to add
> these Enums to a Set without throwing a ClassCastException
> regardless of which class, anonymous inner class or whatever else the
> Enum is. 

Well, this is what is excplicitly documented in the JDK's docs for Comparable.compareTo(). The ValueEnum must ensure that it does not compare apples and oranges and two different classes imply this.

The exception was surprising for you, since the old version of CL simply did this, but I'd rather declare that impl of compareTo as buggy ;-)

- Jörg

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Posted by Samuel Fleischle <sf...@key-software.com>.
Hi Jörg,

thanks for your quick response and your approach to solve this issue. But anyway I think it should be possible to add these Enums to a Set without throwing a ClassCastException regardless of which class, anonymous inner class or whatever else the Enum is.

Samuel

-----Original Message-----
From: Jörg Schaible [mailto:Joerg.Schaible@Elsag-Solutions.com] 
Sent: Thursday, September 13, 2007 4:06 PM
To: Jakarta Commons Users List
Subject: RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Hi Samuel,

Samuel Fleischle wrote on Thursday, September 13, 2007 3:51 PM:

> Hi,
> I updated from Commons Lang 2.1 to Commons Lang 2.3 and got
> some issues with the changed compareTo() method of Enum with
> anonymouse inner classes: 
> 
> Here is my simplified Enum:
> 
> 
> public class ItemStatus extends Enum
> {
>        // --------------------------------------------------
> Static Fields
>       public static final ItemStatus CANCEL = new
> ItemStatus("CANCEL", "Cancel");
> 
>        public static final ItemStatus SHIPPED = new
> ItemStatus("SHIPPED", "Shipped") {
>        	public String getDisplayName() {
>        		// do something special for this status
> 		}
>        };
> 
>       public static final ItemStatus MOVED = new
> ItemStatus("MOVED", "Moved") {
>        	public String getDisplayName() {
> 			// do something special for this status
> 		}
>        };
> 

[snip]

> }

[snip]
 
> com.myapp.common.model.order.ItemStatus
> com.myapp.common.model.order.ItemStatus$1
> com.myapp.common.model.order.ItemStatus$2
> 
> The compareTo-Method now tries to compare ItemStatus$1 with
> ItemStatus$2 and says to me, that my ItemStatus-Enums are
> different classes.

Well, obviously those *are* different classes.

> I saw in JIRA there are some other issues in
> ValuedEnum.compareTo(). Is there a bug in the
> Enum.compareTo() implementation which got changed in Lang 2.2?

IIRC, this was more about using different class loaders loading the EnumValue class.
 
> Thanks in advance for any help or comment on this issue.

Why don't you factor out a (private) interface with this method? Write an addition ctor that takes such an implementation and use otherwise a default one. With this approach the enum class is always the same and the anonymous class is of a different type. Make the an additional field in the enum class keeping that implementation and declare it as transient for seamless serialization.

- Jörg

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org





---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Posted by Jörg Schaible <Jo...@Elsag-Solutions.com>.
Hi Samuel,

Samuel Fleischle wrote on Thursday, September 13, 2007 3:51 PM:

> Hi,
> I updated from Commons Lang 2.1 to Commons Lang 2.3 and got
> some issues with the changed compareTo() method of Enum with
> anonymouse inner classes: 
> 
> Here is my simplified Enum:
> 
> 
> public class ItemStatus extends Enum
> {
>        // --------------------------------------------------
> Static Fields
>       public static final ItemStatus CANCEL = new
> ItemStatus("CANCEL", "Cancel");
> 
>        public static final ItemStatus SHIPPED = new
> ItemStatus("SHIPPED", "Shipped") {
>        	public String getDisplayName() {
>        		// do something special for this status
> 		}
>        };
> 
>       public static final ItemStatus MOVED = new
> ItemStatus("MOVED", "Moved") {
>        	public String getDisplayName() {
> 			// do something special for this status
> 		}
>        };
> 

[snip]

> }

[snip]
 
> com.myapp.common.model.order.ItemStatus
> com.myapp.common.model.order.ItemStatus$1
> com.myapp.common.model.order.ItemStatus$2
> 
> The compareTo-Method now tries to compare ItemStatus$1 with
> ItemStatus$2 and says to me, that my ItemStatus-Enums are
> different classes.

Well, obviously those *are* different classes.

> I saw in JIRA there are some other issues in
> ValuedEnum.compareTo(). Is there a bug in the
> Enum.compareTo() implementation which got changed in Lang 2.2?

IIRC, this was more about using different class loaders loading the EnumValue class.
 
> Thanks in advance for any help or comment on this issue.

Why don't you factor out a (private) interface with this method? Write an addition ctor that takes such an implementation and use otherwise a default one. With this approach the enum class is always the same and the anonymous class is of a different type. Make the an additional field in the enum class keeping that implementation and declare it as transient for seamless serialization.

- Jörg

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Posted by Samuel Fleischle <sf...@key-software.com>.
Hi,
I updated from Commons Lang 2.1 to Commons Lang 2.3 and got some issues with the changed compareTo() method of Enum with anonymouse inner classes:

Here is my simplified Enum:


public class ItemStatus extends Enum
{
       // -------------------------------------------------- Static Fields
      public static final ItemStatus CANCEL = new ItemStatus("CANCEL", "Cancel");

       public static final ItemStatus SHIPPED = new ItemStatus("SHIPPED", "Shipped") {
       	public String getDisplayName() {
       		// do something special for this status
		}
       };

      public static final ItemStatus MOVED = new ItemStatus("MOVED", "Moved") {
       	public String getDisplayName() {
			// do something special for this status
		}
       };

       /** Contains each status. */
      private static Set statuses;

	// -------------------------------------------------- Instance Fields
	/** Name to display in user interfaces. */
	private final String displayName;

       // --------------------------------------------------- Constructors

      protected ItemStatus(String name, String displayName) {
            super(name);
       	this.displayName = displayName;
            System.out.println(this.getClass().getName());
            buildStatusSet();
      }

      // --------------------------------------------------- Static Methods

      /**
       * Returns the item status enumeration object
	 * for the given status name.
       * 
       * @param itemStatus
       *            name of the item status
       * @return the enumeration object, or <code>null</code> if it does not
       *         exist
       */
      public static ItemStatus valueOf(String itemStatus) {
            return (ItemStatus) getEnum(ItemStatus.class, itemStatus);
      }

      // --------------------------------------------------- Public Methods

      /**
       * {@inheritDoc}
       */
      // @Override
      public final Class getEnumClass() {
            return ItemStatus.class;
      }

      /**
       * Gets all defined ItemStatus.
       * 
       * @return the enum object List
       * @see org.apache.commons.lang.enums.Enum#getEnumList(Class)
       */
      public static List getEnumList() {
            return getEnumList(ItemStatus.class);
      }

       public String getDisplayName() {
		return displayName;
	}

      // --------------------------------------------------- Private Methods

      /**
       * Adds the status name to a Set of status names.
       */
      private void buildStatusSet() {
            if (statuses == null) {
                  statuses = new TreeSet();
            }
            statuses.add(this);
      }
}

And I got the ClassCastExcetion in the private "buildStatusSet()-Method if I try to add the status to the TreeSet. The TreeSet calls the compareTo-Method of the Enum. In Commons Lang 2.2 this method was changed with an additional comparison of the classes.
In my constructor I added a System.out.println of the instantiated classes and got the following output for the classnames:

com.myapp.common.model.order.ItemStatus
com.myapp.common.model.order.ItemStatus$1
com.myapp.common.model.order.ItemStatus$2

The compareTo-Method now tries to compare ItemStatus$1 with ItemStatus$2 and says to me, that my ItemStatus-Enums are different classes.

I saw in JIRA there are some other issues in ValuedEnum.compareTo(). Is there a bug in the Enum.compareTo() implementation which got changed in Lang 2.2?

Thanks in advance for any help or comment on this issue.

Regards,
Sam


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


RE: [lang] ClassCastException in Enum.compareTo with anonymous inner classes

Posted by Samuel Fleischle <sf...@key-software.com>.
Hi,
I updated from Commons Lang 2.1 to Commons Lang 2.3 and got some issues with the changed compareTo() method of Enum with anonymouse inner classes:

Here is my simplified Enum:


public class ItemStatus extends Enum
{
       // -------------------------------------------------- Static Fields
      public static final ItemStatus CANCEL = new ItemStatus("CANCEL", "Cancel");

       public static final ItemStatus SHIPPED = new ItemStatus("SHIPPED", "Shipped") {
       	public String getDisplayName() {
       		// do something special for this status
		}
       };

      public static final ItemStatus MOVED = new ItemStatus("MOVED", "Moved") {
       	public String getDisplayName() {
			// do something special for this status
		}
       };

       /** Contains each status. */
      private static Set statuses;

	// -------------------------------------------------- Instance Fields
	/** Name to display in user interfaces. */
	private final String displayName;

       // --------------------------------------------------- Constructors

      protected ItemStatus(String name, String displayName) {
            super(name);
       	this.displayName = displayName;
            System.out.println(this.getClass().getName());
            buildStatusSet();
      }

      // --------------------------------------------------- Static Methods

      /**
       * Returns the item status enumeration object
	 * for the given status name.
       * 
       * @param itemStatus
       *            name of the item status
       * @return the enumeration object, or <code>null</code> if it does not
       *         exist
       */
      public static ItemStatus valueOf(String itemStatus) {
            return (ItemStatus) getEnum(ItemStatus.class, itemStatus);
      }

      // --------------------------------------------------- Public Methods

      /**
       * {@inheritDoc}
       */
      // @Override
      public final Class getEnumClass() {
            return ItemStatus.class;
      }

      /**
       * Gets all defined ItemStatus.
       * 
       * @return the enum object List
       * @see org.apache.commons.lang.enums.Enum#getEnumList(Class)
       */
      public static List getEnumList() {
            return getEnumList(ItemStatus.class);
      }

       public String getDisplayName() {
		return displayName;
	}

      // --------------------------------------------------- Private Methods

      /**
       * Adds the status name to a Set of status names.
       */
      private void buildStatusSet() {
            if (statuses == null) {
                  statuses = new TreeSet();
            }
            statuses.add(this);
      }
}

And I got the ClassCastExcetion in the private "buildStatusSet()-Method if I try to add the status to the TreeSet. The TreeSet calls the compareTo-Method of the Enum. In Commons Lang 2.2 this method was changed with an additional comparison of the classes.
In my constructor I added a System.out.println of the instantiated classes and got the following output for the classnames:

com.myapp.common.model.order.ItemStatus
com.myapp.common.model.order.ItemStatus$1
com.myapp.common.model.order.ItemStatus$2

The compareTo-Method now tries to compare ItemStatus$1 with ItemStatus$2 and says to me, that my ItemStatus-Enums are different classes.

I saw in JIRA there are some other issues in ValuedEnum.compareTo(). Is there a bug in the Enum.compareTo() implementation which got changed in Lang 2.2?

Thanks in advance for any help or comment on this issue.

Regards,
Sam


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org