Java JTable返回类型安全值的自定义数据模型

Java JTable返回类型安全值的自定义数据模型,java,swing,jtable,abstracttablemodel,typed,Java,Swing,Jtable,Abstracttablemodel,Typed,假设我正在使用CustomDataModel和CustomTableListener创建一个自定义JTable。假设他们工作出色 现在假设在实现中,每个JTable都保证其第一行填充类型安全数据,并且该数据永远不会被删除、修改,也不会设置为null。(使用JComboxes作为编辑器,将空字符串和0呈现为空字符串是唯一的“空”选择) 现在;我想编写一个使用getColumnClass返回类型化数据的方法 根据我所阅读的内容,我必须结合使用以下方法: class CustomDataModel e

假设我正在使用CustomDataModel和CustomTableListener创建一个自定义JTable。假设他们工作出色

现在假设在实现中,每个JTable都保证其第一行填充类型安全数据,并且该数据永远不会被删除、修改,也不会设置为null。(使用JComboxes作为编辑器,将空字符串和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));
}
}
类CustomDataModel扩展了AbstractTableModel{
...
//实施数据结构和其他方法(SSCCE下面的完整可测试代码)
...
/**
*保证返回基于此表构造的类
*@param c
*@返回
*/
@凌驾
公共类getColumnClass(int c){
返回getValueAt(0,c).getClass();
}
...
公共T返回类型(int行,int列){
//以下内容将无法编译-我被卡住了,不知道如何编译
//使用getColumnClass返回特定于类型的数据
返回getColumnClass(column).cast(getValueAt(行,列));
}
}
NetBeans告诉我cast调用返回Object,但我确信cast(objectobj)返回了T,其中T是cast中的类型

我越想它,我就越相信我想要的东西是不可能的。这并不是真的必要,但它可以避免强制转换——尽管我认为如果我当前的实现通过手动强制转换得到“修复”和类型化检索,这将强制执行强制转换

现在;在SSCCE中,我使用system.out.println只是打印-它接收一个对象引用并调用其toString()方法,但我想要执行的方法或操作不一定要绑定到对象参数

关键是直接获取存储的数据类型;如果它存储为对象引用而不将其转换回其原始类型,我想这是不可能的。。。除非使用仿制药?我不知道-感谢您的帮助

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);
        }
    }
}
//包实用程序;
导入java.awt.Dimension;
导入java.awt.GridLayout;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.List;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTable;
导入javax.swing.table.AbstractTableModel;
/**
*@作者肖恩
*/
公共类单元测试扩展了JPanel{
公共单元测试(){
超级(新网格布局(1,0));
JTable table=createAJTable();
table.getTableHeader().setReorderingAllowed(false);
表.setPreferredScrollableViewportSize(新维度(500,70));
表.setFillsViewPerthweight(真);
//创建滚动窗格并将表添加到其中。
JScrollPane scrollPane=新的JScrollPane(表);
//通常情况下,JComboxes设置为编辑器-SSCCE将使用虚拟测试数据
//将滚动窗格添加到此面板。
添加(滚动窗格);
//测试数据类型-我希望检索特定于类型的数据以避免强制转换
CustomModel dataModel=(CustomModel)table.getModel();
对象val;
对于(int row=0;row