dimanche 11 mai 2014

Erreur du compilateur à l'aide de generics Java Interface avec JavaFX Collection - Stack Overflow


I'm trying to use an interface with a JavaFX ListView to allow multiple object types to be displayed in the list at different points in the application (different Object type on different GUI screens. I have defined the ListView in my JavaFX controller class as:


@FXML private static ListView<? extends ListDisplayObj> lvLeftBarItems;

and ListDisplayObj is a simple interface:


public interface ListDisplayObj
{
public String getListDisplayString();
}

I have a database-level method which obtains a list of objects to be displayed based on a given key - the method is defined as:


public ObservableList<? extends ListDisplayObj> getListObjectsForKey(String selectedKey)
{
...
}

Later in the controller event handler (or initialize() method) I am trying to initialize the ListView using an ObservableList as follows:


ObservableList<? extends ListDisplayObj> ol = MyObjectManager.getListObjectsForKey(selectedKey);
lvLeftBarItems.setItems(ol);

The lvLeftBarItems.setItems(ol) call generates the following compiler error (in Netbeans)::


incompatible types: ObservableList<CAP#1> cannot be converted to ObservableList<CAP#2>
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends ListDisplayObj from capture of ? extends ListDisplayObj
CAP#2 extends ListDisplayObj from capture of ? extends ListDisplayObj

Any suggestions? I'm not sure how to resolve this. I've tried variations on using the raw Object (which implements ListDisplayObj) instead of <? extends ListDisplayObj>, just returning <ListDisplayObj> vs <? extends ListDisplayObj>, etc with no luck.




When you have a list whose element type is X you can store any object whose type is X or subclass of X.


ListView<? extends ListDisplayObj> lvLeftBarItems;

This declaration means that lvLeftBarItems is a ListView whose contents are some unspecified subclass of ListDisplayObj, lets name it CAP#1 (i know it is not a valid class name, but lets pass it for example purposes).


You are trying to add an element whose type is technically unspecified subclass of ListDisplayObj too, but lets name it CAP#2.


Now assume that CAP#1 extends ListDisplayObj and CAP#2 extends ListDisplayObj , so it is obvious that you can not cast an instance of CAP#1 to CAP#2 or vice-verse, and it follows that you can not cast a list of CAP#1 to a list of CAP#2, and this is exactly what compiler means when it says that "ObservableList cannot be converted to ObservableList" - these lists have a different incompatible type, because list items have a different incompatible type.


Check GenericsFAQ: Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type for a more detailed explanation.


As for your code, simply replace the declaration of lvLeftBarItems to non-wildcard generic:


ListView<ListDisplayObj> lvLeftBarItems;


I'm trying to use an interface with a JavaFX ListView to allow multiple object types to be displayed in the list at different points in the application (different Object type on different GUI screens. I have defined the ListView in my JavaFX controller class as:


@FXML private static ListView<? extends ListDisplayObj> lvLeftBarItems;

and ListDisplayObj is a simple interface:


public interface ListDisplayObj
{
public String getListDisplayString();
}

I have a database-level method which obtains a list of objects to be displayed based on a given key - the method is defined as:


public ObservableList<? extends ListDisplayObj> getListObjectsForKey(String selectedKey)
{
...
}

Later in the controller event handler (or initialize() method) I am trying to initialize the ListView using an ObservableList as follows:


ObservableList<? extends ListDisplayObj> ol = MyObjectManager.getListObjectsForKey(selectedKey);
lvLeftBarItems.setItems(ol);

The lvLeftBarItems.setItems(ol) call generates the following compiler error (in Netbeans)::


incompatible types: ObservableList<CAP#1> cannot be converted to ObservableList<CAP#2>
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends ListDisplayObj from capture of ? extends ListDisplayObj
CAP#2 extends ListDisplayObj from capture of ? extends ListDisplayObj

Any suggestions? I'm not sure how to resolve this. I've tried variations on using the raw Object (which implements ListDisplayObj) instead of <? extends ListDisplayObj>, just returning <ListDisplayObj> vs <? extends ListDisplayObj>, etc with no luck.



When you have a list whose element type is X you can store any object whose type is X or subclass of X.


ListView<? extends ListDisplayObj> lvLeftBarItems;

This declaration means that lvLeftBarItems is a ListView whose contents are some unspecified subclass of ListDisplayObj, lets name it CAP#1 (i know it is not a valid class name, but lets pass it for example purposes).


You are trying to add an element whose type is technically unspecified subclass of ListDisplayObj too, but lets name it CAP#2.


Now assume that CAP#1 extends ListDisplayObj and CAP#2 extends ListDisplayObj , so it is obvious that you can not cast an instance of CAP#1 to CAP#2 or vice-verse, and it follows that you can not cast a list of CAP#1 to a list of CAP#2, and this is exactly what compiler means when it says that "ObservableList cannot be converted to ObservableList" - these lists have a different incompatible type, because list items have a different incompatible type.


Check GenericsFAQ: Which methods and fields are accessible/inaccessible through a reference variable of a wildcard parameterized type for a more detailed explanation.


As for your code, simply replace the declaration of lvLeftBarItems to non-wildcard generic:


ListView<ListDisplayObj> lvLeftBarItems;

0 commentaires:

Enregistrer un commentaire