title: Custom DataModel for JTable return Type-Safe value
body: <p>Suppose I am creating a custom JTable with CustomDataModel and CustomTableListener. Suppose they work gloriously.</p>
  
  <p>Now suppose in the implementation that <strong>every JTable is guaranteed to have its first row populated with type-safe data, and that that data will never get deleted, only modified - and never set to null.</strong> (using JComboBoxes as their editor, and empty String's and 0's that get rendered as empty strings are the only "empty" choice)</p>
  
  <p>Now; I want to write a method that uses <em>getColumnClass</em> to return typed-data.</p>
  
  <p>From what I've read I'll have to use the following methods in conjunction:</p>
  
  <pre><code>class CustomDataModel extends AbstractTableModel {
  ...
  //implement data struc and other methods (full testable code further down below in the SSCCE)
  ...
  
  /**
   * Guaranteed to return a class based on this table's construction
   * @param c
   * @return 
   */
  @Override
  public Class getColumnClass(int c){
      return getValueAt(0,c).getClass();
  }
  
  ...
  
  public &lt;T&gt; T returnType(int row, int column) {
      //the following will not compile - and I'm stuck, don't know how to
      //use getColumnClass to return type-specific data
      return getColumnClass(column).cast(getValueAt(row,column));
  }
  }
  </code></pre>
  
  <p>NetBeans tells me that the cast invocation returns Object, but I was sure that cast(Object obj) returned T, where T is the type of this in cast.</p>
  
  <p>The more I think about it, the more that I believe that I what I desire is impossible. It's not really necessary, but it would avoid casts - although I suppose this would force casts to be done if my current implementation gets "fixed" and typed-retrieval done through manual casting.</p>
  
  <p>Now; in the SSCCE I use system.out.println to just print - which takes in an Object reference and invokes its toString() method, but the methods or actions I want to take I don't necessarily want to be bound to an Object parameter.</p>
  
  <p>The point is to directly get the type of the data stored; which isn't really possible if it's stored as an Object reference without casting it back to its original type I suppose... Unless generics are used? I don't know - any help appreciated!</p>
  
  <p><strong>SSCCE</strong></p>
  
  <pre><code>//package utility;
  
  import java.awt.Dimension;
  import java.awt.GridLayout;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  import javax.swing.JFrame;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.JTable;
  import javax.swing.table.AbstractTableModel;
  
  /**
   * @author Sean
   */
  public class UnitTesting extends JPanel{
  
      public UnitTesting() {
          super(new GridLayout(1,0));
  
          JTable table = createAJTable();
          table.getTableHeader().setReorderingAllowed(false);
          table.setPreferredScrollableViewportSize(new Dimension(500, 70));
          table.setFillsViewportHeight(true);
  
          //Create the scroll pane and add the table to it.
          JScrollPane scrollPane = new JScrollPane(table);
  
          //Normally here JComboBoxes are set as the Editors - SSCCE will use dummy test data
  
          //Add the scroll pane to this panel.
          add(scrollPane);
  
          //Test the data Types - I want to retrieve type-specific data to avoid casting
          CustomModel dataModel = (CustomModel)table.getModel();
          Object val;
          for(int row = 0; row &lt; dataModel.getRowCount(); row++){
              //Row possibility
              doSomeThings(row, dataModel);
              for(int col = 0; col &lt; dataModel.getColumnCount(); col++){
                  //Here's the old way of going about this. (also could invoke getColumnClass())
                  val = dataModel.getValueAt(row, col);
                  System.out.println(val + " : " + val.getClass());
                  //Overloaded possibility - needs typed data
  //                doSomeAction(dataModel.typedValueAt(row, col));
              }
          }
      }
  
      private JTable createAJTable() {
          return new JTable(new CustomModel(new String[]{"Col1", "Col2", "Col3", "Col4", "Col5"}));
      }
  
      private void doSomeAction(String str){
          //Do things with strings
      }
  
      private void doSomeAction(int number){
          //Do things with integers
      }
  
      private void doSomeThings(int row, CustomModel dataModel) {
          String col1Data, col2Data, col5Data;
          int col3Num, col4Num;
          //Retrieve data and store it in typed local variable (need casting or typed retrieval)
          //Do things with the Strings and Integers together
      }
  
      /**
       * Create the GUI and show it.  For thread safety,
       * this method should be invoked from the
       * event-dispatching thread.
       */
      private static void createAndShowGUI() {
          //Create and set up the window.
          JFrame frame = new JFrame("TableDemo");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
          //Create and set up the content pane.
          UnitTesting newContentPane = new UnitTesting();
          newContentPane.setOpaque(true); //content panes must be opaque
          frame.setContentPane(newContentPane);
  
          //Display the window.
          frame.pack();
          frame.setVisible(true);
      }
  
      public static void main(String[] args) {
          /*
           * Set Look and feel here; taken out for SSCCE
           */
          //Schedule a job for the event-dispatching thread:
          //creating and showing this application's GUI.
          javax.swing.SwingUtilities.invokeLater(new Runnable() {
              @Override
              public void run() {
                  createAndShowGUI();
              }
          });
      }
  
      class CustomModel extends AbstractTableModel {
          //Dummy data for the SSCCE
          private List&lt;String&gt; columnHeadings;
          private List&lt;List&lt;Object&gt;&gt; data;
  
          CustomModel(String[] cols){
              data = new ArrayList&lt;&gt;();
              columnHeadings = Arrays.asList(cols);
  
              ArrayList&lt;Object&gt; testRow = new ArrayList&lt;&gt;();
              testRow.add("String");
              testRow.add("Str");
              testRow.add(0);
              testRow.add(5);
              testRow.add("Strong");
  
              data.add(testRow);
          }
  
          //This is the method I want to create
  //        public &lt;T&gt; T typedValueAt(int row, int column) {
  //            return getColumnClass(column).cast(getValueAt(row,column));
  //        }
  
          @Override
          public int getRowCount() {
              return data.size();
          }
  
          @Override
          public int getColumnCount() {
              return columnHeadings.size();
          }
  
          @Override
          public String getColumnName(int columnIndex) {
              return columnHeadings.get(columnIndex);
          }
  
          @Override
          public Class&lt;?&gt; getColumnClass(int c) {
              return getValueAt(0,c).getClass();
          }
  
          @Override
          public boolean isCellEditable(int rowIndex, int columnIndex) {
              //For the SSCCE we'll just test with one row of uneditable data
              return false;
          }
  
          @Override
          public Object getValueAt(int rowIndex, int columnIndex) {
              return data.get(rowIndex).get(columnIndex);
          }
  
          @Override
          public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
              //Normally check for row existence and populate necessary rows - but for SSCCE just this will suffice
              data.get(rowIndex).set(columnIndex, aValue);
          }
      }
  }
  </code></pre>