<Swing Dev> [PATCH] 6179357: Generics: JList

Florian Brunner fbrunnerlist at gmx.ch
Thu May 14 13:59:27 UTC 2009


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




More information about the swing-dev mailing list