JDK-8186648 : Addition of generics to some Swing classes breaks existing code
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 9,10,11
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: generic
  • CPU: generic
  • Submitted: 2017-08-22
  • Updated: 2019-01-30
  • Resolved: 2019-01-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 13
13Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
openjdk version "9-Ubuntu"
OpenJDK Runtime Environment (build 9-Ubuntu+0-9b181-2)
OpenJDK 64-Bit Server VM (build 9-Ubuntu+0-9b181-2, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux astoria 4.10.0-32-generic #36-Ubuntu SMP Tue Aug 8 12:10:06 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
The class "javax.swing.tree.DefaultMutableTreeNode" has gained generics on some protected fields which are for client usage. It contained raw Vector previously, now contains a Vector<TreeNode>.

This breaks existing code horribly, as clients must use their own TreeNode extension, e.g. in the Electric VLSI tool here:
https://sources.debian.net/src/electric/9.07%2Bdfsg-2/com/sun/electric/tool/user/ui/JobTree.java/#L50

children = [..] new Vector<JobTreeNode>();

Also the addition of generics to the "Enumeration children()" requires code changes, but not as horrible. Also left broken in the code example below.

Perhaps this field should be <? extends TreeNode>? Or the class should be generic?

REGRESSION.  Last worked in version 8u144


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

class MyNode implements TreeNode {
  public boolean isLeaf() { return false; }
  public TreeNode getParent() { return null; }
  public int getIndex(TreeNode node) { return 0; }
  public int getChildCount() { return 0; }
  public TreeNode getChildAt(int childIndex) { return null; }
  public boolean getAllowsChildren() { return false; }
  public Enumeration<?> children() { return null; }
}

class A extends DefaultMutableTreeNode {
  A() {
    children = new Vector<MyNode>();
  }
}

---------- END SOURCE ----------


Comments
Arguably, the various classes implementing the TreeNode interface should have their children methods return Enumeration<? extends TreeNode> rather than Enumeration<TreeNode>. However, that improvement would not address the case in hand.
15-01-2019

MyNode.java:13: error: children() in MyNode cannot implement children() in TreeNode public Enumeration<?> children() { return null; } ^ Should be fixed as public Enumeration<? extends TreeNode> children() { return null;} MyNode.java:18: error: incompatible types: Vector<MyNode> cannot be converted to Vector<TreeNode> children = new Vector<MyNode>(); should be fixed as children = new Vector<TreeNode>(); The framework code cannot be changed as suggested by the bug, since that makes the field pretty much immutable, and does not allow addition and deletion of child nodes to the field. Hence, it is expected that the clients cast the object to appropriate class type once they retrieve it from the children field.
13-10-2017

The generification in question was done under JDK-8043550. Refinements to other aspects of the generification were done under JDK-8054360.
23-08-2017

This issue is started from 9 ea b02. 9 ea b01 - Pass 9 ea b02 - Fail
23-08-2017

This issue is reproducible only on 9. 8u144 - Pass 8u152 - Pass 9 ea b181 - Fail == jdk/9/all/181/binaries/linux-x64/bin/javac MyNode.java MyNode.java:6: error: MyNode is not abstract and does not override abstract method children() in TreeNode class MyNode implements TreeNode { ^ MyNode.java:13: error: children() in MyNode cannot implement children() in TreeNode public Enumeration<?> children() { return null; } ^ return type Enumeration<?> is not compatible with Enumeration<? extends TreeNode> MyNode.java:18: error: incompatible types: Vector<MyNode> cannot be converted to Vector<TreeNode> children = new Vector<MyNode>(); ^ 3 errors
23-08-2017