Hi Florian,
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?
I think the same way.
So we don't risk anything by not introducing that parameter right now,
if we don't see any benefit.
What do you think?
I agree that we can introduce that parameter later if needed.
Regards, Pavel.
-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