javagenericsjcombobox

JComboBox CustomModel Generics Warning


Pure Java 8 without IDE. I have a Problem creating a JComboBox with Custom Model without Warnings because of Generics. My goal is to have a dynamic Object List, where the Name of the Objects is displayed in the JComboBox and can be selected there. The Data Objects are in a DataLink Class with several Properties and one Method toString() that returns the Name of the Object as String. Then I have a Custom ComboBoxModel called ComboModel. It extends AbstractListModel and implements ComboBoxModel. It operates with items of the Object Class that it holds in a ArrayList. It holds the selectedIndex value and overrides the 4 Methods getElementAt(), getSize(), getSelectedItem(), setSelectedItem(). Additinally it implemtes clear(), size(), get(), add() and remove() to operate on the arrayList. Then I have a DataLinkModel class (this additionally implements Methods to act as a JTableModel as well, but not important here and now). It uses the beforementioned ComboModel to store its Elements, that are of type DataLink. It has a Method public ComboModel getComboList(), to return the ComboModel, to pass it to a JComboBox Constructor or setModel() Method. The DataLinkModel is created in a DataClass as dataLink that has a Method public ComboModel getDataLinkComboList() that returns dataLink.getComboList(). In a JFrame I have now this declaration and instancing (the DataClass is instanced before):

JComboBox<String>   comboDataObject;
comboDataObject = new JComboBox<>((ComboBoxModel<String>)dataClass.getDataLinkComboList()); // Line 3649

this syntax gives (with Xlint:unchecked):

AppFrame.java:3649: warning: [unchecked] unchecked cast required: ComboBoxModel<String> found:    ComboModel 1 warning

I tried that with givin the type as DataLink, or ComboModel, or DataLinkModel in different combinations. Sometimes I get two Warnings, sometimes one, but always warnings. I dont have a clue how to tell the Type. Skipping the cast warns for unchecked conversion. At least its a String that is coming from the toString() Method in the DataLink Object that should be shown in the JComboBox. In looked here and googled, I only found string[] solutions, never complex object lists.
Beside the warnings the app works as expected. How do I instanciate correctly?

Code Structure (not compilable, but could make the description clear):

public class DataLink {
    ... several properties, getter, setter
    public String toString() {
        return name;
    }
}
class ComboModel extends AbstractListModel implements ComboBoxModel {
    List<Object>    data;
    int         selectedIndex;
    public ComboModel() {
        data        = new ArrayList<Object>();
        selectedIndex   = -1;
    }
    public Object getElementAt(int index)   // Overides operate on data list
    public int getSize()
    public Object getSelectedItem()
    public void setSelectedItem(Object anItem)
    // Custom methods:
    public void clear()
    public int size()
    public Object get(int index)
    public void add(Object object)
    public void remove(int index)   // remove, add and clear after data change have: fireContentsChanged(this, -1, -1);
}
public class DataLinkModel extends AbstractTableModel {
    ComboModel comboList;
    public DataLinkModel() {
        comboList = new ComboModel();
    }
    public ComboModel getComboList() {
        return comboList;
    }
    ... some methods to extend abstractTableModel
    ... methods as proxie methods that operate on the comboList(add, remove etc).
}
public class DataClass {
    DataLinkModel   dataLink;
    ...
    public DataClass() {
        dataLink = new DataLinkModel();
        createDataInDataLink();
    }
    public ComboModel getDataLinkComboList() {
        return dataLink.getComboList();
    }
    ...
}

Thanks, Frankie


Solution

  • You are getting warnings because of raw types in your ComboModel (List<Object>), but trying to cast it to ComboBoxModel<String>. This unchecked cast causes the compiler warning.

    To fix warnings in your code, try to parameterise your ComboModel with a generic type, as shown below

    class ComboModel<T> extends AbstractListModel<T> implements ComboBoxModel<T> {
        List<T> data = new ArrayList<>();
        int selectedIndex = -1;
    
        public T getElementAt(int index) { return data.get(index); }
        public int getSize() { return data.size(); }
        public T getSelectedItem() { return selectedIndex >= 0 ? data.get(selectedIndex) : null; }
        public void setSelectedItem(Object anItem) { selectedIndex = data.indexOf(anItem); }
    
        // Custom methods
        public void clear() { data.clear(); fireContentsChanged(this, -1, -1); }
        public int size() { return data.size(); }
        public T get(int index) { return data.get(index); }
        public void add(T object) { data.add(object); fireContentsChanged(this, -1, -1); }
        public void remove(int index) { data.remove(index); fireContentsChanged(this, -1, -1); }
    }
    

    Then, use it as shown below.

    The JComboBox will display the names via toString() and no cast or warning is needed.

    ComboModel<DataLink> model = dataClass.getDataLinkComboList();  
    
    // assuming return type is ComboModel<DataLink>
    JComboBox<DataLink> combo = new JComboBox<>(model);