6823603: Generics: JList
authorrupashka
Mon, 23 Nov 2009 20:57:17 +0300
changeset 4378 ef21a120cb18
parent 4283 06d5378aaff3
child 4379 ce28939f55fc
6823603: Generics: JList Reviewed-by: peterz, alexp Contributed-by: fbrunnerlist@gmx.ch
jdk/src/share/classes/javax/swing/AbstractListModel.java
jdk/src/share/classes/javax/swing/DefaultListCellRenderer.java
jdk/src/share/classes/javax/swing/DefaultListModel.java
jdk/src/share/classes/javax/swing/JList.java
jdk/src/share/classes/javax/swing/ListCellRenderer.java
jdk/src/share/classes/javax/swing/ListModel.java
jdk/test/javax/swing/JList/6823603/bug6823603.java
--- a/jdk/src/share/classes/javax/swing/AbstractListModel.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/AbstractListModel.java	Mon Nov 23 20:57:17 2009 +0300
@@ -42,9 +42,11 @@
  * has been added to the <code>java.beans</code> package.
  * Please see {@link java.beans.XMLEncoder}.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Hans Muller
  */
-public abstract class AbstractListModel implements ListModel, Serializable
+public abstract class AbstractListModel<E> implements ListModel<E>, Serializable
 {
     protected EventListenerList listenerList = new EventListenerList();
 
--- a/jdk/src/share/classes/javax/swing/DefaultListCellRenderer.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/DefaultListCellRenderer.java	Mon Nov 23 20:57:17 2009 +0300
@@ -71,7 +71,7 @@
  * @author Hans Muller
  */
 public class DefaultListCellRenderer extends JLabel
-    implements ListCellRenderer, Serializable
+    implements ListCellRenderer<Object>, Serializable
 {
 
    /**
@@ -111,7 +111,7 @@
     }
 
     public Component getListCellRendererComponent(
-        JList list,
+        JList<?> list,
         Object value,
         int index,
         boolean isSelected,
--- a/jdk/src/share/classes/javax/swing/DefaultListModel.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/DefaultListModel.java	Mon Nov 23 20:57:17 2009 +0300
@@ -48,11 +48,13 @@
  * has been added to the <code>java.beans</code> package.
  * Please see {@link java.beans.XMLEncoder}.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Hans Muller
  */
-public class DefaultListModel extends AbstractListModel
+public class DefaultListModel<E> extends AbstractListModel<E>
 {
-    private Vector delegate = new Vector();
+    private Vector<E> delegate = new Vector<E>();
 
     /**
      * Returns the number of components in this list.
@@ -83,7 +85,7 @@
      *             list
      * @see #get(int)
      */
-    public Object getElementAt(int index) {
+    public E getElementAt(int index) {
         return delegate.elementAt(index);
     }
 
@@ -175,7 +177,7 @@
      * @return  an enumeration of the components of this list
      * @see Vector#elements()
      */
-    public Enumeration<?> elements() {
+    public Enumeration<E> elements() {
         return delegate.elements();
     }
 
@@ -260,7 +262,7 @@
      * @see #get(int)
      * @see Vector#elementAt(int)
      */
-    public Object elementAt(int index) {
+    public E elementAt(int index) {
         return delegate.elementAt(index);
     }
 
@@ -271,7 +273,7 @@
      * @return     the first component of this list
      * @see Vector#firstElement()
      */
-    public Object firstElement() {
+    public E firstElement() {
         return delegate.firstElement();
     }
 
@@ -283,13 +285,13 @@
      * @return  the last component of the list
      * @see Vector#lastElement()
      */
-    public Object lastElement() {
+    public E lastElement() {
         return delegate.lastElement();
     }
 
     /**
      * Sets the component at the specified <code>index</code> of this
-     * list to be the specified object. The previous component at that
+     * list to be the specified element. The previous component at that
      * position is discarded.
      * <p>
      * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
@@ -300,13 +302,13 @@
      *    <code>List</code> interface defined in the 1.2 Collections framework.
      * </blockquote>
      *
-     * @param      obj     what the component is to be set to
+     * @param      element what the component is to be set to
      * @param      index   the specified index
      * @see #set(int,Object)
      * @see Vector#setElementAt(Object,int)
      */
-    public void setElementAt(Object obj, int index) {
-        delegate.setElementAt(obj, index);
+    public void setElementAt(E element, int index) {
+        delegate.setElementAt(element, index);
         fireContentsChanged(this, index, index);
     }
 
@@ -331,7 +333,7 @@
     }
 
     /**
-     * Inserts the specified object as a component in this list at the
+     * Inserts the specified element as a component in this list at the
      * specified <code>index</code>.
      * <p>
      * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
@@ -342,26 +344,26 @@
      *    <code>List</code> interface defined in the 1.2 Collections framework.
      * </blockquote>
      *
-     * @param      obj     the component to insert
+     * @param      element the component to insert
      * @param      index   where to insert the new component
      * @exception  ArrayIndexOutOfBoundsException  if the index was invalid
      * @see #add(int,Object)
      * @see Vector#insertElementAt(Object,int)
      */
-    public void insertElementAt(Object obj, int index) {
-        delegate.insertElementAt(obj, index);
+    public void insertElementAt(E element, int index) {
+        delegate.insertElementAt(element, index);
         fireIntervalAdded(this, index, index);
     }
 
     /**
      * Adds the specified component to the end of this list.
      *
-     * @param   obj   the component to be added
+     * @param   element   the component to be added
      * @see Vector#addElement(Object)
      */
-    public void addElement(Object obj) {
+    public void addElement(E element) {
         int index = delegate.size();
-        delegate.addElement(obj);
+        delegate.addElement(element);
         fireIntervalAdded(this, index, index);
     }
 
@@ -441,7 +443,7 @@
      *
      * @param index index of element to return
      */
-    public Object get(int index) {
+    public E get(int index) {
         return delegate.elementAt(index);
     }
 
@@ -457,8 +459,8 @@
      * @param element element to be stored at the specified position
      * @return the element previously at the specified position
      */
-    public Object set(int index, Object element) {
-        Object rv = delegate.elementAt(index);
+    public E set(int index, E element) {
+        E rv = delegate.elementAt(index);
         delegate.setElementAt(element, index);
         fireContentsChanged(this, index, index);
         return rv;
@@ -474,7 +476,7 @@
      * @param index index at which the specified element is to be inserted
      * @param element element to be inserted
      */
-    public void add(int index, Object element) {
+    public void add(int index, E element) {
         delegate.insertElementAt(element, index);
         fireIntervalAdded(this, index, index);
     }
@@ -488,9 +490,10 @@
      * (<code>index &lt; 0 || index &gt;= size()</code>).
      *
      * @param index the index of the element to removed
+     * @return the element previously at the specified position
      */
-    public Object remove(int index) {
-        Object rv = delegate.elementAt(index);
+    public E remove(int index) {
+        E rv = delegate.elementAt(index);
         delegate.removeElementAt(index);
         fireIntervalRemoved(this, index, index);
         return rv;
--- a/jdk/src/share/classes/javax/swing/JList.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/JList.java	Mon Nov 23 20:57:17 2009 +0300
@@ -25,11 +25,24 @@
 
 package javax.swing;
 
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GraphicsEnvironment;
+import java.awt.HeadlessException;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
 import java.awt.event.*;
-import java.awt.*;
 
 import java.util.Vector;
 import java.util.Locale;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
@@ -59,28 +72,30 @@
  * constructor that automatically builds a read-only {@code ListModel} instance
  * for you:
  * <pre>
+ * {@code
  * // Create a JList that displays strings from an array
  *
  * String[] data = {"one", "two", "three", "four"};
- * JList myList = new JList(data);
+ * JList<String> myList = new JList<String>(data);
  *
  * // Create a JList that displays the superclasses of JList.class, by
  * // creating it with a Vector populated with this data
  *
- * Vector superClasses = new Vector();
- * Class rootClass = javax.swing.JList.class;
- * for(Class cls = rootClass; cls != null; cls = cls.getSuperclass()) {
+ * Vector<Class<?>> superClasses = new Vector<Class<?>>();
+ * Class<JList> rootClass = javax.swing.JList.class;
+ * for(Class<?> cls = rootClass; cls != null; cls = cls.getSuperclass()) {
  *     superClasses.addElement(cls);
  * }
- * JList myList = new JList(superClasses);
+ * JList<Class<?>> myList = new JList<Class<?>>(superClasses);
  *
  * // The automatically created model is stored in JList's "model"
  * // property, which you can retrieve
  *
- * ListModel model = myList.getModel();
+ * ListModel<Class<?>> model = myList.getModel();
  * for(int i = 0; i < model.getSize(); i++) {
  *     System.out.println(model.getElementAt(i));
  * }
+ * }
  * </pre>
  * <p>
  * A {@code ListModel} can be supplied directly to a {@code JList} by way of a
@@ -103,12 +118,14 @@
  * notifying listeners. For example, a read-only implementation of
  * {@code AbstractListModel}:
  * <pre>
+ * {@code
  * // This list model has about 2^16 elements.  Enjoy scrolling.
  *
- * ListModel bigData = new AbstractListModel() {
+ * ListModel<String> bigData = new AbstractListModel<String>() {
  *     public int getSize() { return Short.MAX_VALUE; }
- *     public Object getElementAt(int index) { return "Index " + index; }
+ *     public String getElementAt(int index) { return "Index " + index; }
  * };
+ * }
  * </pre>
  * <p>
  * The selection state of a {@code JList} is managed by another separate
@@ -150,9 +167,10 @@
  * component to render, is installed by the lists's {@code ListUI}. You can
  * substitute your own renderer using code like this:
  * <pre>
+ * {@code
  *  // Display an icon and a string for each object in the list.
  *
- * class MyCellRenderer extends JLabel implements ListCellRenderer {
+ * class MyCellRenderer extends JLabel implements ListCellRenderer<Object> {
  *     final static ImageIcon longIcon = new ImageIcon("long.gif");
  *     final static ImageIcon shortIcon = new ImageIcon("short.gif");
  *
@@ -160,7 +178,7 @@
  *     // We just reconfigure the JLabel each time we're called.
  *
  *     public Component getListCellRendererComponent(
- *       JList list,              // the list
+ *       JList<?> list,           // the list
  *       Object value,            // value to display
  *       int index,               // cell index
  *       boolean isSelected,      // is the cell selected
@@ -184,6 +202,7 @@
  * }
  *
  * myList.setCellRenderer(new MyCellRenderer());
+ * }
  * </pre>
  * <p>
  * Another job for the cell renderer is in helping to determine sizing
@@ -195,7 +214,8 @@
  * automatically based on a single prototype value:
  * <a name="prototype_example">
  * <pre>
- * JList bigDataList = new JList(bigData);
+ * {@code
+ * JList<String> bigDataList = new JList<String>(bigData);
  *
  * // We don't want the JList implementation to compute the width
  * // or height of all of the list cells, so we give it a string
@@ -204,6 +224,7 @@
  * // properties.
  *
  * bigDataList.setPrototypeCellValue("Index 1234567890");
+ * }
  * </pre>
  * <p>
  * {@code JList} doesn't implement scrolling directly. To create a list that
@@ -260,13 +281,15 @@
  * @see ListCellRenderer
  * @see DefaultListCellRenderer
  *
+ * @param <E> the type of the elements of this list
+ *
  * @beaninfo
  *   attribute: isContainer false
  * description: A component which allows for the selection of one or more objects from a list.
  *
  * @author Hans Muller
  */
-public class JList extends JComponent implements Scrollable, Accessible
+public class JList<E> extends JComponent implements Scrollable, Accessible
 {
     /**
      * @see #getUIClassID
@@ -301,15 +324,15 @@
     private int fixedCellWidth = -1;
     private int fixedCellHeight = -1;
     private int horizontalScrollIncrement = -1;
-    private Object prototypeCellValue;
+    private E prototypeCellValue;
     private int visibleRowCount = 8;
     private Color selectionForeground;
     private Color selectionBackground;
     private boolean dragEnabled;
 
     private ListSelectionModel selectionModel;
-    private ListModel dataModel;
-    private ListCellRenderer cellRenderer;
+    private ListModel<E> dataModel;
+    private ListCellRenderer<? super E> cellRenderer;
     private ListSelectionListener selectionListener;
 
     /**
@@ -402,7 +425,7 @@
      * @param dataModel the model for the list
      * @exception IllegalArgumentException if the model is {@code null}
      */
-    public JList(ListModel dataModel)
+    public JList(ListModel<E> dataModel)
     {
         if (dataModel == null) {
             throw new IllegalArgumentException("dataModel must be non null");
@@ -437,12 +460,12 @@
      * @param  listData  the array of Objects to be loaded into the data model,
      *                   {@code non-null}
      */
-    public JList(final Object[] listData)
+    public JList(final E[] listData)
     {
         this (
-            new AbstractListModel() {
+            new AbstractListModel<E>() {
                 public int getSize() { return listData.length; }
-                public Object getElementAt(int i) { return listData[i]; }
+                public E getElementAt(int i) { return listData[i]; }
             }
         );
     }
@@ -462,11 +485,11 @@
      * @param  listData  the <code>Vector</code> to be loaded into the
      *                   data model, {@code non-null}
      */
-    public JList(final Vector<?> listData) {
+    public JList(final Vector<? extends E> listData) {
         this (
-            new AbstractListModel() {
+            new AbstractListModel<E>() {
                 public int getSize() { return listData.size(); }
-                public Object getElementAt(int i) { return listData.elementAt(i); }
+                public E getElementAt(int i) { return listData.elementAt(i); }
             }
         );
     }
@@ -477,9 +500,9 @@
      */
     public JList() {
         this (
-            new AbstractListModel() {
+            new AbstractListModel<E>() {
               public int getSize() { return 0; }
-              public Object getElementAt(int i) { return "No Data Model"; }
+              public E getElementAt(int i) { throw new IndexOutOfBoundsException("No Data Model"); }
             }
         );
     }
@@ -526,7 +549,7 @@
     public void updateUI() {
         setUI((ListUI)UIManager.getUI(this));
 
-        ListCellRenderer renderer = getCellRenderer();
+        ListCellRenderer<? super E> renderer = getCellRenderer();
         if (renderer instanceof Component) {
             SwingUtilities.updateComponentTreeUI((Component)renderer);
         }
@@ -560,8 +583,8 @@
      */
     private void updateFixedCellSize()
     {
-        ListCellRenderer cr = getCellRenderer();
-        Object value = getPrototypeCellValue();
+        ListCellRenderer<? super E> cr = getCellRenderer();
+        E value = getPrototypeCellValue();
 
         if ((cr != null) && (value != null)) {
             Component c = cr.getListCellRendererComponent(this, value, 0, false, false);
@@ -592,7 +615,7 @@
      * @return the value of the {@code prototypeCellValue} property
      * @see #setPrototypeCellValue
      */
-    public Object getPrototypeCellValue() {
+    public E getPrototypeCellValue() {
         return prototypeCellValue;
     }
 
@@ -632,8 +655,8 @@
      *   attribute: visualUpdate true
      * description: The cell prototype value, used to compute cell width and height.
      */
-    public void setPrototypeCellValue(Object prototypeCellValue) {
-        Object oldValue = this.prototypeCellValue;
+    public void setPrototypeCellValue(E prototypeCellValue) {
+        E oldValue = this.prototypeCellValue;
         this.prototypeCellValue = prototypeCellValue;
 
         /* If the prototypeCellValue has changed and is non-null,
@@ -727,7 +750,7 @@
      * @see #setCellRenderer
      */
     @Transient
-    public ListCellRenderer getCellRenderer() {
+    public ListCellRenderer<? super E> getCellRenderer() {
         return cellRenderer;
     }
 
@@ -755,8 +778,8 @@
      *   attribute: visualUpdate true
      * description: The component used to draw the cells.
      */
-    public void setCellRenderer(ListCellRenderer cellRenderer) {
-        ListCellRenderer oldValue = this.cellRenderer;
+    public void setCellRenderer(ListCellRenderer<? super E> cellRenderer) {
+        ListCellRenderer<? super E> oldValue = this.cellRenderer;
         this.cellRenderer = cellRenderer;
 
         /* If the cellRenderer has changed and prototypeCellValue
@@ -1455,7 +1478,7 @@
      * @since 1.4
      */
     public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
-        ListModel model = getModel();
+        ListModel<E> model = getModel();
         int max = model.getSize();
         if (prefix == null) {
             throw new IllegalArgumentException();
@@ -1469,16 +1492,16 @@
         int increment = (bias == Position.Bias.Forward) ? 1 : -1;
         int index = startIndex;
         do {
-            Object o = model.getElementAt(index);
-
-            if (o != null) {
+            E element = model.getElementAt(index);
+
+            if (element != null) {
                 String string;
 
-                if (o instanceof String) {
-                    string = ((String)o).toUpperCase();
+                if (element instanceof String) {
+                    string = ((String)element).toUpperCase();
                 }
                 else {
-                    string = o.toString();
+                    string = element.toString();
                     if (string != null) {
                         string = string.toUpperCase();
                     }
@@ -1516,7 +1539,7 @@
         if(event != null) {
             Point p = event.getPoint();
             int index = locationToIndex(p);
-            ListCellRenderer r = getCellRenderer();
+            ListCellRenderer<? super E> r = getCellRenderer();
             Rectangle cellBounds;
 
             if (index != -1 && r != null && (cellBounds =
@@ -1634,7 +1657,7 @@
      *                          list of items
      * @see #setModel
      */
-    public ListModel getModel() {
+    public ListModel<E> getModel() {
         return dataModel;
     }
 
@@ -1656,11 +1679,11 @@
      *   attribute: visualUpdate true
      * description: The object that contains the data to be drawn by this JList.
      */
-    public void setModel(ListModel model) {
+    public void setModel(ListModel<E> model) {
         if (model == null) {
             throw new IllegalArgumentException("model must be non null");
         }
-        ListModel oldValue = dataModel;
+        ListModel<E> oldValue = dataModel;
         dataModel = model;
         firePropertyChange("model", oldValue, dataModel);
         clearSelection();
@@ -1668,7 +1691,7 @@
 
 
     /**
-     * Constructs a read-only <code>ListModel</code> from an array of objects,
+     * Constructs a read-only <code>ListModel</code> from an array of items,
      * and calls {@code setModel} with this model.
      * <p>
      * Attempts to pass a {@code null} value to this method results in
@@ -1676,15 +1699,15 @@
      * references the given array directly. Attempts to modify the array
      * after invoking this method results in undefined behavior.
      *
-     * @param listData an array of {@code Objects} containing the items to
+     * @param listData an array of {@code E} containing the items to
      *        display in the list
      * @see #setModel
      */
-    public void setListData(final Object[] listData) {
+    public void setListData(final E[] listData) {
         setModel (
-            new AbstractListModel() {
+            new AbstractListModel<E>() {
                 public int getSize() { return listData.length; }
-                public Object getElementAt(int i) { return listData[i]; }
+                public E getElementAt(int i) { return listData[i]; }
             }
         );
     }
@@ -1703,11 +1726,11 @@
      *                                          display in the list
      * @see #setModel
      */
-    public void setListData(final Vector<?> listData) {
+    public void setListData(final Vector<? extends E> listData) {
         setModel (
-            new AbstractListModel() {
+            new AbstractListModel<E>() {
                 public int getSize() { return listData.size(); }
-                public Object getElementAt(int i) { return listData.elementAt(i); }
+                public E getElementAt(int i) { return listData.elementAt(i); }
             }
         );
     }
@@ -2235,10 +2258,13 @@
      * @see #isSelectedIndex
      * @see #getModel
      * @see #addListSelectionListener
+     *
+     * @deprecated As of JDK 1.7, replaced by {@link #getSelectedValuesList()}
      */
+    @Deprecated
     public Object[] getSelectedValues() {
         ListSelectionModel sm = getSelectionModel();
-        ListModel dm = getModel();
+        ListModel<E> dm = getModel();
 
         int iMin = sm.getMinSelectionIndex();
         int iMax = sm.getMaxSelectionIndex();
@@ -2259,6 +2285,37 @@
         return rv;
     }
 
+    /**
+     * Returns a list of all the selected items, in increasing order based
+     * on their indices in the list.
+     *
+     * @return the selected items, or an empty list if nothing is selected
+     * @see #isSelectedIndex
+     * @see #getModel
+     * @see #addListSelectionListener
+     *
+     * @since 1.7
+     */
+    public List<E> getSelectedValuesList() {
+        ListSelectionModel sm = getSelectionModel();
+        ListModel<E> dm = getModel();
+
+        int iMin = sm.getMinSelectionIndex();
+        int iMax = sm.getMaxSelectionIndex();
+
+        if ((iMin < 0) || (iMax < 0)) {
+            return Collections.emptyList();
+        }
+
+        List<E> selectedItems = new ArrayList<E>();
+        for(int i = iMin; i <= iMax; i++) {
+            if (sm.isSelectedIndex(i)) {
+                selectedItems.add(dm.getElementAt(i));
+            }
+        }
+        return selectedItems;
+    }
+
 
     /**
      * Returns the smallest selected cell index; <i>the selection</i> when only
@@ -2291,7 +2348,7 @@
      * @see #getModel
      * @see #addListSelectionListener
      */
-    public Object getSelectedValue() {
+    public E getSelectedValue() {
         int i = getMinSelectionIndex();
         return (i == -1) ? null : getModel().getElementAt(i);
     }
@@ -2309,7 +2366,7 @@
             setSelectedIndex(-1);
         else if(!anObject.equals(getSelectedValue())) {
             int i,c;
-            ListModel dm = getModel();
+            ListModel<E> dm = getModel();
             for(i=0,c=dm.getSize();i<c;i++)
                 if(anObject.equals(dm.getElementAt(i))){
                     setSelectedIndex(i);
@@ -3138,14 +3195,14 @@
            */
         protected class AccessibleJListChild extends AccessibleContext
                 implements Accessible, AccessibleComponent {
-            private JList     parent = null;
+            private JList<E>     parent = null;
             private int       indexInParent;
             private Component component = null;
             private AccessibleContext accessibleContext = null;
-            private ListModel listModel;
-            private ListCellRenderer cellRenderer = null;
-
-            public AccessibleJListChild(JList parent, int indexInParent) {
+            private ListModel<E> listModel;
+            private ListCellRenderer<? super E> cellRenderer = null;
+
+            public AccessibleJListChild(JList<E> parent, int indexInParent) {
                 this.parent = parent;
                 this.setAccessibleParent(parent);
                 this.indexInParent = indexInParent;
@@ -3175,7 +3232,7 @@
                 if ((parent != null)
                         && (listModel != null)
                         && cellRenderer != null) {
-                    Object value = listModel.getElementAt(index);
+                    E value = listModel.getElementAt(index);
                     boolean isSelected = parent.isSelectedIndex(index);
                     boolean isFocussed = parent.isFocusOwner()
                             && (index == parent.getLeadSelectionIndex());
--- a/jdk/src/share/classes/javax/swing/ListCellRenderer.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/ListCellRenderer.java	Mon Nov 23 20:57:17 2009 +0300
@@ -33,12 +33,13 @@
  * the cells in a JList.  For example, to use a JLabel as a
  * ListCellRenderer, you would write something like this:
  * <pre>
- * class MyCellRenderer extends JLabel implements ListCellRenderer {
+ * {@code
+ * class MyCellRenderer extends JLabel implements ListCellRenderer<Object> {
  *     public MyCellRenderer() {
  *         setOpaque(true);
  *     }
  *
- *     public Component getListCellRendererComponent(JList list,
+ *     public Component getListCellRendererComponent(JList<?> list,
  *                                                   Object value,
  *                                                   int index,
  *                                                   boolean isSelected,
@@ -75,14 +76,17 @@
  *         return this;
  *     }
  * }
+ * }
  * </pre>
  *
+ * @param <E> the type of values this renderer can be used for
+ *
  * @see JList
  * @see DefaultListCellRenderer
  *
  * @author Hans Muller
  */
-public interface ListCellRenderer
+public interface ListCellRenderer<E>
 {
     /**
      * Return a component that has been configured to display the specified
@@ -104,8 +108,8 @@
      * @see ListModel
      */
     Component getListCellRendererComponent(
-        JList list,
-        Object value,
+        JList<? extends E> list,
+        E value,
         int index,
         boolean isSelected,
         boolean cellHasFocus);
--- a/jdk/src/share/classes/javax/swing/ListModel.java	Wed Nov 18 17:36:46 2009 +0300
+++ b/jdk/src/share/classes/javax/swing/ListModel.java	Mon Nov 23 20:57:17 2009 +0300
@@ -35,10 +35,12 @@
  * length of the data model must be reported to all of the
  * ListDataListeners.
  *
+ * @param <E> the type of the elements of this model
+ *
  * @author Hans Muller
  * @see JList
  */
-public interface ListModel
+public interface ListModel<E>
 {
   /**
    * Returns the length of the list.
@@ -51,7 +53,7 @@
    * @param index the requested index
    * @return the value at <code>index</code>
    */
-  Object getElementAt(int index);
+  E getElementAt(int index);
 
   /**
    * Adds a listener to the list that's notified each time a change
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JList/6823603/bug6823603.java	Mon Nov 23 20:57:17 2009 +0300
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+   @bug 6823603
+   @summary Generics: JList
+   @author Florian Brunner
+   @run main bug6823603
+ */
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.awt.*;
+import javax.swing.*;
+
+public class bug6823603 {
+
+    private static final String TEST_ELEMENT = "Test1";
+
+    /**
+     * @param args the command line arguments
+     */
+    @SuppressWarnings("unchecked")
+    public static void main(String[] args) {
+        testRawSignatures();
+        testGenericSignatures();
+
+        testGetSelectedValuesList(); // new method
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void testRawSignatures() {
+        // Test JList
+        ListModel rawTestModel = new DefaultListModel();
+
+        new JList();
+        new JList(rawTestModel);
+        new JList(new Object[]{TEST_ELEMENT});
+        JList rawTestList = new JList(new Vector());
+        rawTestList.getPrototypeCellValue();
+        rawTestList.setPrototypeCellValue(TEST_ELEMENT);
+        rawTestList.getCellRenderer();
+        rawTestList.setCellRenderer(new DefaultListCellRenderer());
+        rawTestList.getModel();
+        rawTestList.setModel(rawTestModel);
+        rawTestList.setListData(new Object[]{TEST_ELEMENT});
+        rawTestList.setListData(new Vector());
+
+        @SuppressWarnings("deprecation")
+        Object[] selectedValues = rawTestList.getSelectedValues();
+        rawTestList.getSelectedValue();
+
+        // Test ListCellRenderer
+        ListCellRenderer rawTestCellRenderer = new DefaultListCellRenderer();
+        String testEntry = "Test";
+        @SuppressWarnings("unchecked")
+        JList rawJList = new JList(new Object[]{testEntry});
+
+        rawTestCellRenderer.getListCellRendererComponent(rawJList,
+                testEntry, 0, true, true);
+
+        // Test ListModel
+        DefaultListModel testModel = new DefaultListModel();
+        testModel.addElement(TEST_ELEMENT);
+        rawTestModel = testModel;
+        rawTestModel.getElementAt(0);
+
+        // Test DefaultListModel
+        DefaultListModel defaultListModel = new DefaultListModel();
+
+        defaultListModel.addElement(TEST_ELEMENT);
+        defaultListModel.getElementAt(0);
+        defaultListModel.elements();
+        defaultListModel.elementAt(0);
+        defaultListModel.firstElement();
+        defaultListModel.lastElement();
+
+        String testElement2 = "Test2";
+
+        defaultListModel.setElementAt(testElement2, 0);
+        defaultListModel.insertElementAt(TEST_ELEMENT, 0);
+        defaultListModel.get(0);
+        defaultListModel.set(0, testElement2);
+        defaultListModel.add(0, TEST_ELEMENT);
+        defaultListModel.remove(0);
+
+        // Test AbstractListModel
+        @SuppressWarnings("serial")
+        ListModel abstractListModel = new AbstractListModel() {
+            public int getSize() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+
+            public Object getElementAt(int index) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        };
+
+        // Test DefaultListCellRenderer
+        DefaultListCellRenderer cellRenderer = new DefaultListCellRenderer();
+
+        @SuppressWarnings("unchecked")
+        JList list = new JList(new Object[]{testEntry});
+
+        cellRenderer.getListCellRendererComponent(rawJList, testEntry, 0, true, true);
+    }
+
+    private static <E> void testGenericSignatures() {
+        // Test JList
+        ListModel<String> stringListModel = new DefaultListModel<String>();
+
+        new JList<String>();
+        new JList<String>(stringListModel);
+        new JList<String>(new String[]{TEST_ELEMENT});
+
+        JList<String> stringTestList = new JList<String>(new Vector<String>());
+
+        stringTestList.getPrototypeCellValue();
+        stringTestList.setPrototypeCellValue(TEST_ELEMENT);
+
+        ListCellRenderer<? super String> cellRenderer = stringTestList.getCellRenderer();
+
+        stringTestList.setCellRenderer(new DefaultListCellRenderer());
+
+        ListModel<String> model = stringTestList.getModel();
+
+        stringTestList.setModel(stringListModel);
+        stringTestList.setListData(new String[]{TEST_ELEMENT});
+        stringTestList.setListData(new Vector<String>());
+
+        @SuppressWarnings("deprecation")
+        Object[] selectedValues = stringTestList.getSelectedValues();
+
+        stringTestList.getSelectedValue();
+
+        // Test ListCellRenderer
+        ListCellRenderer<Object> stringTestCellRenderer =
+                new DefaultListCellRenderer();
+        String testEntry = "Test";
+        JList<String> stringJList = new JList<String>(new String[]{testEntry});
+
+        Component listCellRendererComponent2 =
+                stringTestCellRenderer.getListCellRendererComponent(stringJList,
+                testEntry, 0, true, true);
+
+        // Test ListModel
+        DefaultListModel<String> testModel = new DefaultListModel<String>();
+        testModel.addElement(TEST_ELEMENT);
+        stringListModel = testModel;
+
+        String element1 = stringListModel.getElementAt(0);
+
+        // Test DefaultListModel
+        DefaultListModel<String> stringTestModel = new DefaultListModel<String>();
+
+        stringTestModel.addElement(TEST_ELEMENT);
+        element1 = stringTestModel.getElementAt(0);
+        Enumeration<String> elements = stringTestModel.elements();
+        String element2 = stringTestModel.elementAt(0);
+        String firstElement = stringTestModel.firstElement();
+        String lastElement = stringTestModel.lastElement();
+
+        String testElement2 = "Test2";
+        stringTestModel.setElementAt(testElement2, 0);
+        stringTestModel.insertElementAt(TEST_ELEMENT, 0);
+        String element3 = stringTestModel.get(0);
+        String element4 = stringTestModel.set(0, testElement2);
+        stringTestModel.add(0, TEST_ELEMENT);
+        String removedElement = stringTestModel.remove(0);
+
+        // Test AbstractListModel
+        stringListModel = new AbstractListModel<String>() {
+
+            public int getSize() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+
+            public String getElementAt(int index) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        };
+
+        @SuppressWarnings("serial")
+        ListModel<E> genericTestModel = new AbstractListModel<E>() {
+
+            public int getSize() {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+
+            public E getElementAt(int index) {
+                throw new UnsupportedOperationException("Not supported yet.");
+            }
+        };
+
+        // Test DefaultListCellRenderer
+        cellRenderer = new DefaultListCellRenderer();
+
+        stringJList = new JList<String>(new String[]{testEntry});
+
+        listCellRendererComponent2 = cellRenderer.getListCellRendererComponent(stringJList, testEntry, 0, true, true);
+    }
+
+    private static void testGetSelectedValuesList() {
+        Vector<Integer> data = new Vector<Integer>();
+        for (int i = 0; i < 10; i++) {
+            data.add(i);
+        }
+        JList<Integer> list = new JList<Integer>(data);
+        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        list.setSelectedIndices(new int[]{1, 2, 3, 5, 6, 8});
+
+        @SuppressWarnings("deprecation")
+        Object[] expectedSelectedValues = list.getSelectedValues();
+        List<Integer> selectedValuesList = list.getSelectedValuesList();
+        assertEquals(expectedSelectedValues, selectedValuesList.toArray());
+    }
+
+    private static void assertEquals(Object[] expectedArray,
+            Object[] actualArray) {
+        if (!Arrays.equals(expectedArray, actualArray)) {
+            throw new RuntimeException("Expected: " + Arrays.toString(
+                    expectedArray) + " but was: " + Arrays.toString(actualArray));
+        }
+    }
+}