<Swing Dev> JDK 9 RFR of JDK-8054360: Refine generification of javax.swing
Joe Darcy
joe.darcy at oracle.com
Fri Aug 8 02:20:55 UTC 2014
Hello,
Please review my changes for
JDK-8054360: Refine generification of javax.swing h
http://cr.openjdk.java.net/~darcy/8054360.3/
Full patch below.
This resolves many of the source incompatibility exemplars Jan Lahoda
found in a corpus of programs using swing.
A few comments on the changes.
It seems many existing implementations of the TreeNode interface have a
covariant override of the old raw
Enumeration children();
method which returns an enumeration of the specific TreeNode
implementation type. The revised generification of
Enumeration<? extends TreeNode> children();
allows those existing implementations to still compile. This is a
lower-impact way of allowing those types to still compile compared to
trying to add a type variable to TreeNode.
After some expert generics advice from Dan Smith, I but together a
different generification of
src/share/classes/javax/swing/table/DefaultTableModel.java
which has better source compatibility. Quoting from the changes:
73 @SuppressWarnings("rawtypes")
74 protected Vector<Vector> dataVector;
75
76 /** The <code>Vector</code> of column identifiers. */
77 @SuppressWarnings("rawtypes")
78 protected Vector columnIdentifiers;
79 // Unfortunately, for greater source compatibility the inner-most
80 // Vector in the two fields above is being left raw. The Vector is
81 // read as well as written so using Vector<?> is not suitable and
82 // using Vector<Object> (without adding copying of input Vectors),
83 // would disallow existing code that used, say, a Vector<String>
84 // as an input parameter.
The setter methods used for these fields are changes to have parameters
of type Vector<?> and Vector<? extends Vector>, respectively.
The type Vector<? extends Vector> is the most general type which
captures the implicit constraint of the dataVector field: it is a Vector
of other Vectors. (It would probably be possible to update dataVector to
the somewhat more general Vector<List>, but that would require changes
to the code in other methods of the class.)
The changes in
src/share/classes/sun/tools/jconsole/inspector/TableSorter.java change
the code back to how it was before the swing generification changes went
in based on the changes to DefaultTableModel.
Once the exact generification is settled, I'll file the internal ccc
paperwork.
Early feedback on using this revised generification on swing code is
welcome!
Thanks,
-Joe
--- old/src/share/classes/javax/swing/JSlider.java 2014-08-07
16:53:58.000000000 -0700
+++ new/src/share/classes/javax/swing/JSlider.java 2014-08-07
16:53:58.000000000 -0700
@@ -138,7 +138,7 @@
/**
* {@code Dictionary} of what labels to draw at which values
*/
- private Dictionary<Integer, JComponent> labelTable;
+ private Dictionary<Integer, ? extends JComponent> labelTable;
/**
@@ -773,7 +773,7 @@
}
// Check that there is a label with such image
- Enumeration<JComponent> elements = labelTable.elements();
+ Enumeration<? extends JComponent> elements = labelTable.elements();
while (elements.hasMoreElements()) {
JComponent component = elements.nextElement();
@@ -797,7 +797,7 @@
* @return the <code>Dictionary</code> containing labels and
* where to draw them
*/
- public Dictionary<Integer, JComponent> getLabelTable() {
+ public Dictionary<Integer, ? extends JComponent> getLabelTable() {
/*
if ( labelTable == null && getMajorTickSpacing() > 0 ) {
setLabelTable( createStandardLabels( getMajorTickSpacing()
) );
@@ -830,8 +830,8 @@
* attribute: visualUpdate true
* description: Specifies what labels will be drawn for any given
value.
*/
- public void setLabelTable( Dictionary<Integer, JComponent> labels ) {
- Dictionary<Integer, JComponent> oldTable = labelTable;
+ public void setLabelTable( Dictionary<Integer, ? extends
JComponent> labels ) {
+ Dictionary<Integer, ? extends JComponent> oldTable = labelTable;
labelTable = labels;
updateLabelUIs();
firePropertyChange("labelTable", oldTable, labelTable );
@@ -852,7 +852,7 @@
* @see JComponent#updateUI
*/
protected void updateLabelUIs() {
- Dictionary<Integer, JComponent> labelTable = getLabelTable();
+ Dictionary<Integer, ? extends JComponent> labelTable =
getLabelTable();
if (labelTable == null) {
return;
@@ -866,9 +866,9 @@
}
private void updateLabelSizes() {
- Dictionary<Integer, JComponent> labelTable = getLabelTable();
+ Dictionary<Integer, ? extends JComponent> labelTable =
getLabelTable();
if (labelTable != null) {
- Enumeration<JComponent> labels = labelTable.elements();
+ Enumeration<? extends JComponent> labels =
labelTable.elements();
while (labels.hasMoreElements()) {
JComponent component = labels.nextElement();
component.setSize(component.getPreferredSize());
@@ -1017,7 +1017,7 @@
SmartHashtable table = new SmartHashtable( increment, start );
- Dictionary<Integer, JComponent> labelTable = getLabelTable();
+ Dictionary<Integer, ? extends JComponent> labelTable =
getLabelTable();
if (labelTable != null && (labelTable instanceof
PropertyChangeListener)) {
removePropertyChangeListener((PropertyChangeListener)
labelTable);
--- old/src/share/classes/javax/swing/JTable.java 2014-08-07
16:53:59.000000000 -0700
+++ new/src/share/classes/javax/swing/JTable.java 2014-08-07
16:53:59.000000000 -0700
@@ -669,7 +669,8 @@
* @param rowData the data for the new table
* @param columnNames names of each column
*/
- public JTable(Vector<Vector<Object>> rowData, Vector<Object>
columnNames) {
+ @SuppressWarnings("rawtypes")
+ public JTable(Vector<? extends Vector> rowData, Vector<?>
columnNames) {
this(new DefaultTableModel(rowData, columnNames));
}
--- old/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java
2014-08-07 16:54:00.000000000 -0700
+++ new/src/share/classes/javax/swing/plaf/basic/BasicSliderUI.java
2014-08-07 16:54:00.000000000 -0700
@@ -397,10 +397,10 @@
protected boolean labelsHaveSameBaselines() {
if (!checkedLabelBaselines) {
checkedLabelBaselines = true;
- Dictionary<?, JComponent> dictionary = slider.getLabelTable();
+ Dictionary<Integer, ? extends JComponent> dictionary =
slider.getLabelTable();
if (dictionary != null) {
sameLabelBaselines = true;
- Enumeration<JComponent> elements = dictionary.elements();
+ Enumeration<? extends JComponent> elements =
dictionary.elements();
int baseline = -1;
while (elements.hasMoreElements()) {
JComponent label = elements.nextElement();
@@ -753,7 +753,7 @@
}
protected int getWidthOfWidestLabel() {
- Dictionary<?, JComponent> dictionary = slider.getLabelTable();
+ Dictionary<?, ? extends JComponent> dictionary =
slider.getLabelTable();
int widest = 0;
if ( dictionary != null ) {
Enumeration<?> keys = dictionary.keys();
@@ -766,7 +766,7 @@
}
protected int getHeightOfTallestLabel() {
- Dictionary<?, JComponent> dictionary = slider.getLabelTable();
+ Dictionary<?, ? extends JComponent> dictionary =
slider.getLabelTable();
int tallest = 0;
if ( dictionary != null ) {
Enumeration<?> keys = dictionary.keys();
@@ -871,7 +871,7 @@
* @since 1.6
*/
protected Integer getLowestValue() {
- Dictionary<Integer, JComponent> dictionary =
slider.getLabelTable();
+ Dictionary<Integer, ? extends JComponent> dictionary =
slider.getLabelTable();
if (dictionary == null) {
return null;
@@ -1121,7 +1121,7 @@
public void paintLabels( Graphics g ) {
Rectangle labelBounds = labelRect;
- Dictionary<Integer, JComponent> dictionary =
slider.getLabelTable();
+ Dictionary<Integer, ? extends JComponent> dictionary =
slider.getLabelTable();
if ( dictionary != null ) {
Enumeration<Integer> keys = dictionary.keys();
int minValue = slider.getMinimum();
--- old/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java
2014-08-07 16:54:02.000000000 -0700
+++ new/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java
2014-08-07 16:54:01.000000000 -0700
@@ -392,7 +392,7 @@
trackRect.x = insetCache.left;
trackRect.width = contentRect.width;
- Dictionary<Integer, JComponent> dictionary =
slider.getLabelTable();
+ Dictionary<Integer, ? extends JComponent> dictionary =
slider.getLabelTable();
if (dictionary != null) {
int minValue = slider.getMinimum();
int maxValue = slider.getMaximum();
--- old/src/share/classes/javax/swing/table/DefaultTableModel.java
2014-08-07 16:54:03.000000000 -0700
+++ new/src/share/classes/javax/swing/table/DefaultTableModel.java
2014-08-07 16:54:02.000000000 -0700
@@ -70,10 +70,18 @@
* The <code>Vector</code> of <code>Vectors</code> of
* <code>Object</code> values.
*/
- protected Vector<Vector<Object>> dataVector;
+ @SuppressWarnings("rawtypes")
+ protected Vector<Vector> dataVector;
/** The <code>Vector</code> of column identifiers. */
- protected Vector<Object> columnIdentifiers;
+ @SuppressWarnings("rawtypes")
+ protected Vector columnIdentifiers;
+ // Unfortunately, for greater source compatibility the inner-most
+ // Vector in the two fields above is being left raw. The Vector is
+ // read as well as written so using Vector<?> is not suitable and
+ // using Vector<Object> (without adding copying of input Vectors),
+ // would disallow existing code that used, say, a Vector<String>
+ // as an input parameter.
//
// Constructors
@@ -121,7 +129,7 @@
* @see #setDataVector
* @see #setValueAt
*/
- public DefaultTableModel(Vector<Object> columnNames, int rowCount) {
+ public DefaultTableModel(Vector<?> columnNames, int rowCount) {
setDataVector(newVector(rowCount), columnNames);
}
@@ -156,7 +164,8 @@
* @see #getDataVector
* @see #setDataVector
*/
- public DefaultTableModel(Vector<Vector<Object>> data,
Vector<Object> columnNames) {
+ @SuppressWarnings("rawtypes")
+ public DefaultTableModel(Vector<? extends Vector> data, Vector<?>
columnNames) {
setDataVector(data, columnNames);
}
@@ -191,7 +200,8 @@
* @see #newRowsAdded
* @see #setDataVector
*/
- public Vector<Vector<Object>> getDataVector() {
+ @SuppressWarnings("rawtypes")
+ public Vector<Vector> getDataVector() {
return dataVector;
}
@@ -219,9 +229,10 @@
* @param columnIdentifiers the names of the columns
* @see #getDataVector
*/
- public void setDataVector(Vector<Vector<Object>> dataVector,
- Vector<Object> columnIdentifiers) {
- this.dataVector = nonNullVector(dataVector);
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ public void setDataVector(Vector<? extends Vector> dataVector,
+ Vector<?> columnIdentifiers) {
+ this.dataVector = nonNullVector((Vector<Vector>)dataVector);
this.columnIdentifiers = nonNullVector(columnIdentifiers);
justifyRows(0, getRowCount());
fireTableStructureChanged();
@@ -267,7 +278,7 @@
if (dataVector.elementAt(i) == null) {
dataVector.setElementAt(new Vector<>(), i);
}
- ((Vector)dataVector.elementAt(i)).setSize(getColumnCount());
+ dataVector.elementAt(i).setSize(getColumnCount());
}
}
@@ -350,7 +361,7 @@
*
* @param rowData optional data of the row being added
*/
- public void addRow(Vector<Object> rowData) {
+ public void addRow(Vector<?> rowData) {
insertRow(getRowCount(), rowData);
}
@@ -374,7 +385,7 @@
* @param rowData optional data of the row being added
* @exception ArrayIndexOutOfBoundsException if the row was invalid
*/
- public void insertRow(int row, Vector<Object> rowData) {
+ public void insertRow(int row, Vector<?> rowData) {
dataVector.insertElementAt(rowData, row);
justifyRows(row, row+1);
fireTableRowsInserted(row, row);
@@ -484,7 +495,7 @@
* to zero columns
* @see #setNumRows
*/
- public void setColumnIdentifiers(Vector<Object> columnIdentifiers) {
+ public void setColumnIdentifiers(Vector<?> columnIdentifiers) {
setDataVector(dataVector, columnIdentifiers);
}
@@ -550,7 +561,8 @@
* @param columnName the identifier of the column being added
* @param columnData optional data of the column being added
*/
- public void addColumn(Object columnName, Vector<Object> columnData) {
+ @SuppressWarnings("unchecked") // Adding element to raw
columnIdentifiers
+ public void addColumn(Object columnName, Vector<?> columnData) {
columnIdentifiers.addElement(columnName);
if (columnData != null) {
int columnSize = columnData.size();
@@ -652,6 +664,7 @@
* column was given
*/
public Object getValueAt(int row, int column) {
+ @SuppressWarnings("unchecked")
Vector<Object> rowVector = dataVector.elementAt(row);
return rowVector.elementAt(column);
}
@@ -668,6 +681,7 @@
* column was given
*/
public void setValueAt(Object aValue, int row, int column) {
+ @SuppressWarnings("unchecked")
Vector<Object> rowVector = dataVector.elementAt(row);
rowVector.setElementAt(aValue, column);
fireTableCellUpdated(row, column);
--- old/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java
2014-08-07 16:54:04.000000000 -0700
+++ new/src/share/classes/javax/swing/tree/DefaultMutableTreeNode.java
2014-08-07 16:54:04.000000000 -0700
@@ -1308,7 +1308,7 @@
}
private final class PreorderEnumeration implements
Enumeration<TreeNode> {
- private final Stack<Enumeration<TreeNode>> stack = new Stack<>();
+ private final Stack<Enumeration<? extends TreeNode>> stack =
new Stack<>();
public PreorderEnumeration(TreeNode rootNode) {
super();
@@ -1322,10 +1322,9 @@
}
public TreeNode nextElement() {
- Enumeration<TreeNode> enumer = stack.peek();
+ Enumeration<? extends TreeNode> enumer = stack.peek();
TreeNode node = enumer.nextElement();
- @SuppressWarnings("unchecked")
- Enumeration<TreeNode> children = node.children();
+ Enumeration<? extends TreeNode> children = node.children();
if (!enumer.hasMoreElements()) {
stack.pop();
@@ -1342,7 +1341,7 @@
final class PostorderEnumeration implements Enumeration<TreeNode> {
protected TreeNode root;
- protected Enumeration<TreeNode> children;
+ protected Enumeration<? extends TreeNode> children;
protected Enumeration<TreeNode> subtree;
public PostorderEnumeration(TreeNode rootNode) {
--- old/src/share/classes/javax/swing/tree/TreeNode.java 2014-08-07
16:54:05.000000000 -0700
+++ new/src/share/classes/javax/swing/tree/TreeNode.java 2014-08-07
16:54:05.000000000 -0700
@@ -99,5 +99,5 @@
*
* @return the children of the receiver as an {@code
Enumeration}
*/
- Enumeration<TreeNode> children();
+ Enumeration<? extends TreeNode> children();
}
--- old/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java
2014-08-07 16:54:06.000000000 -0700
+++ new/src/share/classes/sun/tools/jconsole/inspector/TableSorter.java
2014-08-07 16:54:06.000000000 -0700
@@ -146,7 +146,7 @@
// update row heights in XMBeanAttributes (required by
expandable cells)
if (attrs != null) {
for (int i = 0; i < getRowCount(); i++) {
- Vector<?> data = (Vector) dataVector.elementAt(i);
+ Vector<?> data = dataVector.elementAt(i);
attrs.updateRowHeight(data.elementAt(1), i);
}
}
@@ -217,17 +217,17 @@
}
}
- private Vector<Object> getRow(int row) {
+ private Vector<?> getRow(int row) {
return dataVector.elementAt(row);
}
@SuppressWarnings("unchecked")
- private void setRow(Vector<Object> data, int row) {
+ private void setRow(Vector<?> data, int row) {
dataVector.setElementAt(data,row);
}
private void swap(int i, int j, int column) {
- Vector<Object> data = getRow(i);
+ Vector<?> data = getRow(i);
setRow(getRow(j),i);
setRow(data,j);
More information about the swing-dev
mailing list