10
List<Question> questions = new ArrayList<Question>();
questions.addAll(getAllQuestions()); //returns a set of Questions
Collections.sort(questions, new BeanComparator("questionId")); //org.apache.commons.beanutils.BeanComparator

Under Java 1.5, the above works fine except that the 'new BeanComparator("questionId")' generates an unchecked warning. I do not like warnings. Is there a way I can provide the BeanComparator a type, or do I have to use @SuppressWarnings("unchecked")?

skaffman
  • 398,947
  • 96
  • 818
  • 769
emulcahy
  • 1,055
  • 3
  • 18
  • 28

8 Answers8

10

Options are:

  • Change BeanComparator to implement Comparator<Question>. This is not a real option here, given it is a well-known external library class. People ain't going to let you do it.
  • Fork and modify BeanComparator as above, giving it a different FQN.
  • Wrap the existing BeanComparator with a class that implements Comparator<Question>.
  • Change the type of questions to List<?>.
  • Add a suppress warnings annotation.
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • "Add a suppress warnings annotation". That should be the last resort, should happen only and only when you're 100% sure it's safe. – Marius Burz Nov 30 '09 at 22:34
  • 3
    Well yes. But in situations like this you can be 100% sure. And if you make a mistake the worst you'll get is a ClassCastException in an unexpected place. – Stephen C Nov 30 '09 at 22:38
5

Since BeanComparator isn't generic, you'll just have to suppress.

UPDATE: Actually, if it bothers you enough, you could fork the codebase to make it generic, since it's Open Source.

Hank Gay
  • 70,339
  • 36
  • 160
  • 222
1

Create a generic wrapper class:

public class GenericBeanComparator<T> implements Comparator<T> {
  private final BeanComparator myBeanComparator;

  public GenericBeanComparator(String property) {
    myBeanComparator = new BeanComparator(property);
  }

  public int compare(T o1, T o2) {
    return myBeanComparator.compare(o1, o2);
  }
}

Use it like this:

List<Question> questions = new ArrayList<Question>();
questions.addAll(getAllQuestions()); //returns a set of Questions
Collections.sort(questions, new GenericBeanComparator<Question>("questionId"));
dionm
  • 11
  • 3
1

Unless adding a new generic class at Apache Commons Beanutils, the best I found was to wrap BeanComparator in a new method in my "bean toolbox" :

/**
 * Wrapping of Apache communs BeanComparator. Create a comparator which compares two beans by the specified bean
 * property. Property expression can use Apache's nested, indexed, combinated, mapped syntax. @see <a
 * href="http://commons.apache.org/beanutils/api/org/apache/commons/beanutils/BeanComparator.html">Apache's Bean
 * Comparator</a> for more details.
 * @param <T> generic type
 * @param propertyExpression propertyExpression
 * @return the comparator
 */
@SuppressWarnings("unchecked")
public static <T> Comparator<T> createPropertyComparator(final String propertyExpression) {
    return new BeanComparator(propertyExpression);
}
adriclad
  • 11
  • 1
0

Yes, you are supposed to use @SuppressWarnings("unchecked"). There is no reason to think the comparator not using generics can cause a problem in that case.

Sindri Traustason
  • 5,445
  • 6
  • 48
  • 66
0

You could always switch to using Google Collections.

They support Generics.

Fortyrunner
  • 12,702
  • 4
  • 31
  • 54
0

The only way to remove the warning would be to change the code of BeanComparator, but even if you could, unless you made it a specific wrapper that understands your particular type, the concept wouldn't work well. The class operates on any object by reflection which may or may not have the method. It is inherently not typesafe.

The simplest way around the warning is to implement your own comparator:

 public class QuestionComparator extends Comparator<Question> {
      private BeanComparator peer = new BeanComparator("questionId");

      public int compare(Question o1, Question o2) {
             return peer.compare(o1, o2);
      }
 }

You could also implement equals if it matters, and call the BeanComparator equals method like this:

   public boolean equals(Object o) {
       //boiler plate code here to ensure o is an instance of Question and not null
       return ((QuestionComparator) o).peer.equals(peer);
   }
Yishai
  • 90,445
  • 31
  • 189
  • 263
0

BeanComparator is a very small class. Grab the source code and modify it like this:

public class BeanComparator<E> implements Comparator<E>, Serializable {

And modify your invocation like this:

Collections.sort(yourCollection, new BeanComparator<yourBeanClass>(yourProperty));

And voilà warnings disappeared.

Lluis Martinez
  • 1,963
  • 8
  • 28
  • 42