Hi Pavel,
Hi Florian,

Hi Pavel,

I don't understand, what exactly you want to do. DefaultListCellRender implements ListCellRenderer<Object>, which means it is an implementation, which can be savely (without risking a ClassCastException) be used with ANY object. That is due the fact, that it checks if it is an instance of Icon or else calls Object.toString, which is defined for any Object:

if (value instanceof Icon) {
       setIcon((Icon)value);
       setText("");
   }
   else {
       setIcon(null);
       setText((value == null) ? "" : value.toString());
   }
Ok, that code actually prevents to use generics in the DefaultListCellRender class.
Well, it depends what you mean with "prevents". I guess something like the following would still compile (did not test):

public class DefaultListCellRender<E> implements ListCellRenderer<E>{
public Component getListCellRendererComponent(
     JList<? extends E> list, // or JList<?> ?
     E value,
     int index,
     boolean isSelected,
     boolean cellHasFocus)
 {
     ....
     if (value instanceof Icon) {
        setIcon((Icon)value);
        setText("");
     }
     else {
         setIcon(null);
         setText((value == null) ? "" : value.toString());
     }
    ...
 }
}

But since:
- renderers are consumers (-> "super" keyword is used with wildcards) and Object is the super type of all types
- generics are only used at compile time
- the only generic method is already implemented without casting (except in the case of Icon, which cannot be prevented with generics either)

it "prevents" us from the need of introducing a generic type parameter here. (If you can live with the subclassing issue I mentioned before.)

If later someone really finds a scenario, which needs that generic parameter here (what I doubt), I think it should still be possible to change from:

DefaultListCellRender implements ListCellRenderer<Object>

to

DefaultListCellRender<E> implements ListCellRenderer<E>

without breaking backwards compatibility. Correct?
So we don't risk anything by not introducing that parameter right now, if we don't see any benefit.

What do you think?

-Florian

Thanks, Pavel


There is no gain in calling eg.:
new DefaultListCellRender<Foo>()

because the existing implementation (DefaultListCellRender implements ListCellRenderer<Object>) already handles Foo.

The only limitation is with sub-classing: Subclasses cannot change the parameter type. But this can be solved with using composition instead of inheritance, eg:

public class FooRenderer implements ListCellRenderer<Foo>{
private DefaultListCellRender defaultRenderer = new DefaultListCellRender();

public Component getListCellRendererComponent(
       JList<? extends Foo> list,
       Foo value,
       int index,
       boolean isSelected,
       boolean cellHasFocus)
   {
       doSomethingWithFoo(foo);
return defaultRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
   }

 private void doSomethingWithFoo(Foo foo){
     // do something
 }
}

So, I think the answer is yes, it could be changed, but I see no real benefit and more, client code needs then to specify a parameter, which currently it doesn't.

-Florian

Pavel Porvatov schrieb:
Hi Florian,

I have a question about the DefaultListCellRenderer class. Can we modify it to use generics?

Thanks, Pavel

Reply via email to