2013-11-20 3 views
1

Предположим, что я создаю пользовательский JTable с CustomDataModel и CustomTableListener. Предположим, что они работают славно.Пользовательский DataModel для возврата JTable Тип безопасного значения

Теперь предположим, что в реализации, что каждый JTable, как гарантируется, имеет свой первый ряд, заполненный безопасными по типу данных, и что эти данные никогда не будут удалены, изменены только и не будут установлены в null. (используя JComboBoxes в качестве своего редактора и пустые строки и 0, которые отображаются как пустые строки, являются единственным «пустым» выбором)

Сейчас; Я хочу написать метод, который использует getColumnClass для возврата типизированных данных.

Из того, что я прочитал, я должен буду использовать следующие методы в сочетании:

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 <T> 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)); 
} 
} 

NetBeans рассказывает мне, что возвращается литая Призыва Object, но я был уверен, что литой (Object объект) возвращается T, где T - тип этого в литье.

Чем больше я думаю об этом, тем больше я верю, что я, что хочу, невозможно. На самом деле это не обязательно, но это позволит избежать бросков - хотя я предполагаю, что это заставит делать броски, если моя текущая реализация получит «фиксированную» и набрав-отпечаток, выполненную с помощью ручной кастинга.

В настоящее время; в SSCCE я использую system.out.println, чтобы просто печатать - который принимает ссылку на объект и вызывает его метод toString(), но методы или действия, которые я хочу выполнить, не обязательно должны привязываться к параметру Object ,

Цель состоит в том, чтобы непосредственно получить тип хранимых данных; что на самом деле невозможно, если он хранится в качестве ссылки на объект, не возвращая его в исходный тип. Предположим ... Если не используются дженерики? Я не знаю - любая помощь ценится!

SSCCE

//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 < dataModel.getRowCount(); row++){ 
      //Row possibility 
      doSomeThings(row, dataModel); 
      for(int col = 0; col < 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<String> columnHeadings; 
     private List<List<Object>> data; 

     CustomModel(String[] cols){ 
      data = new ArrayList<>(); 
      columnHeadings = Arrays.asList(cols); 

      ArrayList<Object> testRow = new ArrayList<>(); 
      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 <T> 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<?> 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); 
     } 
    } 
} 
+0

Глядя на следующие ссылки - спуск по общей трассе данных. http://stackoverflow.com/questions/13229979/java-nested-generic-type-mismatch http://stackoverflow.com/questions/8058470/nested-type-parameters-in-java?rq=1 –

ответ

1

Во-первых, getColumnClass(int) должен возвращать класс с информацией общего типа или другого статического типа возвращаемого этой функции будет эффективно Class<Object> и, следовательно, его cast(Object) функция будет иметь тип возвращаемого объекта. Однако это не решит вашу проблему. Корень проблемы состоит в том, что getValueAt(int,int) из AbstractTableModel не несет никакой информации статического типа, кроме объекта (то есть его тип возврата - объект).

Когда вы думаете об этом, getValueAt(int,int) не может вернуть какой-либо статический тип, отличный от Object, поскольку он применяется к каждому столбцу в таблице, и каждый из них может иметь другой тип. Фактически, вы можете добавлять столбцы во время выполнения, о которых даже не думали во время компиляции. Как вы можете определить статически, какой тип этих столбцов имеет?

Скорее всего, вам придется прибегнуть к использованию оператора и выполнения времени выполнения или повторной реализации значительных частей структуры JTable для добавления информации статического типа для каждого столбца (и, скорее всего, потерять возможность добавления столбцов во время выполнения) ,