Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 10 migration issue related to Collection and Generics

In continuation of my previous query in the link: Swing Issue on Java 10, I am finding a few more issues (highlighting only errors), this time I see issues are mostly in Collection API's after moving to java 10.

Below is the error. Wanted to know is there any major changes in Java 10 when migrating from Java 8 (from Collection/Generics point of view).

    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\ui\tree\WMTreeNode.java:159: error: breadthFirstEnumeration() in WMTreeNode cannot override breadthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends WMTreeNode> breadthFirstEnumeration() {
    [javac]                                             ^
    [javac]   return type Enumeration<? extends WMTreeNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\ui\tree\WMTreeNode.java:158: error: method does not override or implement a method from a supertype
    [javac]     @Override
    [javac]     ^
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\ui\tree\WMTreeNode.java:164: error: depthFirstEnumeration() in WMTreeNode cannot override depthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends WMTreeNode> depthFirstEnumeration() {
    [javac]                                             ^
    [javac]   return type Enumeration<? extends WMTreeNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\ui\tree\WMTreeNode.java:163: error: method does not override or implement a method from a supertype
    [javac]     @Override
    [javac]     ^

    [javac]                           ^
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\ui\tree\WMTreeNode.java:298: error: no suitable method found for sort(Vector<TreeNode>)
    [javac]             Collections.sort(children);


[javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\load\LoadNode.java:90: error: breadthFirstEnumeration() in LoadNode cannot override breadthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends LoadNode> breadthFirstEnumeration() {
    [javac]                                           ^
    [javac]   return type Enumeration<? extends LoadNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\load\LoadNode.java:95: error: depthFirstEnumeration() in LoadNode cannot override depthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends LoadNode> depthFirstEnumeration() {


 [javac]   where T is a type-variable:
    [javac]     T extends Object declared in class Class
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\automation\plot\CopyCountJobParameterDescriptor.java:113: error: incompatible types: Integer cannot be converted to CAP#1
    [javac]             final boolean outOfRange = (model.getMinimum().compareTo(i) > 0) || (model.getMaximum().compareTo(i) < 0);
    [javac]                                                                      ^
    [javac]   where CAP#1 is a fresh type-variable:
    [javac]     CAP#1 extends Object from capture of ?
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\automation\plot\CopyCountJobParameterDescriptor.java:113: error: incompatible types: Integer cannot be converted to CAP#1
    [javac]             final boolean outOfRange = (model.getMinimum().compareTo(i) > 0) || (model.getMaximum().compareTo(i) < 0);


    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\load\SnapshotLoadNode.java:48: error: breadthFirstEnumeration() in SnapshotLoadNode cannot override breadthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends SnapshotLoadNode> breadthFirstEnumeration() {
    [javac]                                                   ^
    [javac]   return type Enumeration<? extends SnapshotLoadNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\load\SnapshotLoadNode.java:53: error: depthFirstEnumeration() in SnapshotLoadNode cannot override depthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends SnapshotLoadNode> depthFirstEnumeration() {


    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\favorites\FavoritesTreeNode.java:30: error: breadthFirstEnumeration() in FavoritesTreeNode cannot override breadthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends FavoritesTreeNode> breadthFirstEnumeration() {
    [javac]                                                    ^
    [javac]   return type Enumeration<? extends FavoritesTreeNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\favorites\FavoritesTreeNode.java:35: error: depthFirstEnumeration() in FavoritesTreeNode cannot override depthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends FavoritesTreeNode> depthFirstEnumeration() {


    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\save\SaveNode.java:113: error: breadthFirstEnumeration() in SaveNode cannot override breadthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends SaveNode> breadthFirstEnumeration() {
    [javac]                                           ^
    [javac]   return type Enumeration<? extends SaveNode> is not compatible with Enumeration<TreeNode>
    [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\src\com\osm\datamgmt\ui\save\SaveNode.java:118: error: depthFirstEnumeration() in SaveNode cannot override depthFirstEnumeration() in DefaultMutableTreeNode
    [javac]     public Enumeration<?extends SaveNode> depthFirstEnumeration() {
    [javac]                                           ^


   [javac] C:\WorkSpace\JAVA10\oswm\rel20.10_Patches\WorkManager\OSMWebServices\src\java\com\osm\webservices\legacy\util\MessageAttachmentHandler.java:76: error: cannot find symbol
    [javac]                         attachment.setRawContent(new BufferedInputStream(new FileInputStream(file)),
    [javac]              

                 ^

WMTreeNode is extending javax.swing.tree.DefaultMutableTreeNode.

like image 364
vibhas Avatar asked Jul 30 '18 09:07

vibhas


1 Answers

The problem

If you carefully compare the code in DefaultMutableTreeNode between Java 8 and 10, you will see that return types were generified:

// Java 8 uses `Enumeration` as a "raw type"
public Enumeration breadthFirstEnumeration() { /*...*/ }

// Java 10 uses `Enumeration` as intended: with a type parameter
public Enumeration<TreeNode> breadthFirstEnumeration() { /*...*/ }

Your code is of this kind:

public Enumeration<?extends SnapshotLoadNode> breadthFirstEnumeration() { /*...*/ }

Your code compiles on Java 8, because adding generics to a raw type is possible for compatibility reasons. While there can be problems (actually the same as below), raw types are deemed to be unsafe anyway, so these are to be expected.

It no longer compiles on Java 10, because the original API wants to return a Enumeration<TreeNode>, but your override doesn't do that. Instead it returns an Enumeration of a subtype. Now, for an Enumeration this isn't actually a problem because it's read-only (returning a more specific type is of course always ok), but the compiler doesn't know that (a method could accept a more specific type - that would not be ok).

To understand that last parenthesis in more detail, assume it were a List<TreeNode> and a List<SnapshotLoadNode> instead. Then your API, used as a DefaultMutableTreeNode, would return a list that callers could add TreeNode-s to. But your class still thinks it has a list of a subtype and would get class cast exceptions - not good. Without raw types in play, this lack of type safety is unacceptable and hence the compiler complains.

The solution

If DefaultMutableTreeNode were my code I would change breadthFirstEnumeration to return Enumeration<? extends TreeNode> (I have no idea, why that is not the case). That would make your code compile.

Since that's not an option it looks like you have to do this:

  • loose the more precise type information and change your overrides' returns types to Enumeration<TreeNode>
  • if you need the more precise return type, create a new method:

    public Enumeration<?extends SnapshotLoadNode>
        breadthFirstEnumerationAsSnapshotLoadNode() { /*...*/ }
    
like image 160
Nicolai Parlog Avatar answered Oct 27 '22 09:10

Nicolai Parlog