Java比较器始终以字符串形式读取值

Java比较器始终以字符串形式读取值,java,swing,sorting,jtable,comparator,Java,Swing,Sorting,Jtable,Comparator,在试图找出我问的另一个问题()的答案时,我遇到了另一个问题 我正在实现一个自定义表格行排序器,它创建一个自定义比较器。但是,比较器似乎总是将每个对象作为类型字符串读取。这件事让我困惑不解 如果您在下面的SSCCE中注意到 System.out.println(o1.getClass() + " - " + o2.getClass()); 总是输出Yeild class java.lang.String - class java.lang.String 即使对象[]【】数据数组中的项是不同的类

在试图找出我问的另一个问题()的答案时,我遇到了另一个问题

我正在实现一个自定义
表格行排序器
,它创建一个自定义
比较器
。但是,
比较器
似乎总是将每个
对象
作为类型
字符串
读取。这件事让我困惑不解

如果您在下面的SSCCE中注意到

System.out.println(o1.getClass() + " - " + o2.getClass());
总是输出Yeild

class java.lang.String - class java.lang.String
即使
对象[]【】
数据数组中的项是不同的类型

import java.awt.Component;
import java.util.Comparator;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class Test {

    public static void main(String args[]) {
        JFrame frame = new JFrame();
        JTable table = new JTable();
        Object[][] data = new Object[8][3];
        data[0][0] = 6.5d; data[0][1] = "Name1";
        data[1][0] = new NullClassFiller(); data[1][1] = "Name2";
        data[2][0] = 2.6d; data[2][1] = "Name3";
        data[3][0] = 0d; data[3][1] = "Name4";
        data[4][0] = new NullClassFiller(); data[4][1] = "Name5";
        data[5][0] = -4d; data[5][1] = "Name6";
        data[6][0] = 0d; data[6][1] = "Name7";
        data[7][0] = -4.3d; data[7][1] = "Name8";
        table.setModel(new DefaultTableModel(data, new String[]{"One", "Two"}));

        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
            @Override
            public Comparator<?> getComparator(final int column) {
                Comparator c = new Comparator() {
                    @Override
                    public int compare(Object o1, Object o2) {
                        System.out.println(o1.getClass() + " - " + o2.getClass());
                        if (o1 instanceof NullClassFiller) {
                            return -1;
                        } else if (o2 instanceof NullClassFiller) {
                            return -1;
                        } else {
                            return ((Comparable<Object>) o1).compareTo(o2);
                        }

                    }
                };
                return c;
            }
        };
        table.setRowSorter(sorter);
        table.getColumnModel().getColumn(0).setCellRenderer(new CustomRenderer());
        JScrollPane pane = new JScrollPane(table);
        frame.add(pane);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setSize(500, 500);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    static class NullClassFiller {}

    static class CustomRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            if(value instanceof NullClassFiller)
                renderer.setText("");

            return renderer;
        }

    }
}
导入java.awt.Component;
导入java.util.Comparator;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.JTable;
导入javax.swing.table.DefaultTableCellRenderer;
导入javax.swing.table.DefaultTableModel;
导入javax.swing.table.TableModel;
导入javax.swing.table.TableRowSorter;
公开课考试{
公共静态void main(字符串参数[]){
JFrame=新JFrame();
JTable table=新的JTable();
对象[][]数据=新对象[8][3];
数据[0][0]=6.5d;数据[0][1]=Name1;
数据[1][0]=新的NullClassFiller();数据[1][1]=名称2;
数据[2][0]=2.6d;数据[2][1]=Name3;
数据[3][0]=0d;数据[3][1]=Name4;
数据[4][0]=新的NullClassFiller();数据[4][1]=名称5;
数据[5][0]=-4d;数据[5][1]=“名称6”;
数据[6][0]=0d;数据[6][1]=Name7;
数据[7][0]=-4.3d;数据[7][1]=“名称8”;
setModel(新的DefaultTableModel(数据,新字符串[]{“一”,“二”}));
TableRowSorter-sorter=新的TableRowSorter(table.getModel()){
@凌驾
公共比较器getComparator(最后一个int列){
比较器c=新比较器(){
@凌驾
公共整数比较(对象o1、对象o2){
System.out.println(o1.getClass()+“-”+o2.getClass());
if(NullClassFiller的o1实例){
返回-1;
}else if(NullClassFiller的o2实例){
返回-1;
}否则{
回报率((可比)o1),与(o2)相比;
}
}
};
返回c;
}
};
表.SetRow分拣机(分拣机);
table.getColumnModel().getColumn(0).setCellRenderer(新的CustomRenderer());
JScrollPane=新的JScrollPane(表);
框架。添加(窗格);
frame.pack();
frame.setLocationRelativeTo(空);
框架。设置尺寸(500500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
静态类NullClassFiller{}
静态类CustomRenderer扩展了DefaultTableCellRenderer{
@凌驾
公共组件GetTableCellRenderComponent(JTable表、对象值、布尔isSelected、布尔hasFocus、int行、int列){
DefaultTableCellRenderer=(DefaultTableCellRenderer)super.getTableCellRendererComponent(表、值、isSelected、hasFocus、行、列);
if(NullClassFiller的值实例)
.setText(“”);
返回渲染器;
}
}
}
问题在于:

table.setModel(new DefaultTableModel(data, new String[]{"One", "Two"}));
根据,

有两个JTable构造函数直接接受数据(SimpleTableDemo使用第一个):

他们很容易使用。但是,这些构造函数也有 缺点:

它们会自动使每个单元格都可编辑。它们处理所有数据类型 与字符串相同

问题在于:

table.setModel(new DefaultTableModel(data, new String[]{"One", "Two"}));
根据,

有两个JTable构造函数直接接受数据(SimpleTableDemo使用第一个):

他们很容易使用。但是,这些构造函数也有 缺点:

它们会自动使每个单元格都可编辑。它们处理所有数据类型 与字符串相同


有许多复杂的问题

第一个是使用
DefaultTableModel
DefaultTableModel#getColumnClass
返回
Object.class

第二个是使用
表格行分拣机
TableRowSorter
检查从模型返回的
是否可比,如果不可比,则自动转换为
字符串
,因为
对象
不可比

因此,基本解决方案是覆盖
DefaultTableModel
getColumnClass
,以返回特定列的适当类型的
Class

TableModel model = new DefaultTableModel(data, new String[]{"One", "Two"}) {
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return columnIndex == 0 ? Double.class : String.class;
    }
};
table.setModel(model);

有许多复杂的问题

第一个是使用
DefaultTableModel
DefaultTableModel#getColumnClass
返回
Object.class

第二个是使用
表格行分拣机
TableRowSorter
检查从模型返回的
是否可比,如果不可比,则自动转换为
字符串
,因为
对象
不可比

因此,基本解决方案是覆盖
DefaultTableModel
getColumnClass
,以返回特定列的适当类型的
Class

TableModel model = new DefaultTableModel(data, new String[]{"One", "Two"}) {
    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return columnIndex == 0 ? Double.class : String.class;
    }
};
table.setModel(model);

问题和答案都存在一些问题:

  • 在表的末尾排序空值,而不考虑排序顺序
  • 该需求的干净解决方案需要对DefaultRowSorter及其子类进行几乎完全的重写,因为空值在比较算法中“早期”处理,并且被深埋在其私有内部。简单地说,定制比较器是不可能跳入的
  • 一种方法是不添加null,而是使用专用的null替换,然后让自定义