java - 为什么 setTableHeader() 方法会抛出 NullPointerException?

标签 java swing nullpointerexception jtable jtableheader

我尝试将工具提示添加到我的 JTable 标题中。在本例中,我使用 TTHeader 类,它扩展了 JTableHeader Java 类。一切似乎都很好,但是当我尝试将新的 TTHeader header 添加到我的 JTable 时,我得到了 NullPointerException 且来源未知。我不知道为什么。 TTHeader 类似乎没问题。问题出在其他地方。

这是我的方法的代码。 对于 JTable 填充:

 private JPanel contentPane;
 private JScrollPane scrollPane;
 private JTable table;
 private String tooltipsSDB[] = {"SessionID", "UserID", "PatientID", "PluginID", "Date", "Time"};

 Connection conn = null;
 ResultSet rs = null;
 PreparedStatement ps = null;

 Table() {
      // Connection Component
      conn = ConnectionJDBC.ConnectDB();

      setTitle("My sample table");
      setSize(new Dimension(400, 400));
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setLocationRelativeTo(null);
      setVisible(true);

      contentPane = new JPanel();
      contentPane.setLayout(new BorderLayout(0, 0));
      setContentPane(contentPane);

      scrollPane = new JScrollPane();
      contentPane.add(scrollPane, BorderLayout.CENTER);

      table = new JTable() {
           public boolean isCellEditable(int row, int column) {
                return false;
           };
      };
      table.setAutoCreateRowSorter(true);
      // Populate JTable with data from SQL DB
      populateTable();
      scrollPane.setViewportView(table);
 }

 public void populateTable() {
      String sql = "SELECT * FROM " + ExampleDatabase + " ORDER BY " + ExampleData + " DESC";
      try {
           // Make Connection With DB
           ps = conn.prepareStatement(sql);
           rs = ps.executeQuery();
           ResultSetMetaData rsmetadata = rs.getMetaData();

           // Populate JTable
           int columns = rsmetadata.getColumnCount();
           DefaultTableModel dtm = new DefaultTableModel();
           Vector columns_name = new Vector();
           Vector data_rows = new Vector();
           for (int i = 1; i <= columns; i++) {
                columns_name.addElement(rsmetadata.getColumnName(i));
           }
           dtm.setColumnIdentifiers(columns_name);
           while (rs.next()) {
                data_rows = new Vector();
                for (int j = 1; j <= columns; j++) {
                     data_rows.addElement(rs.getString(j));
                }
                dtm.addRow(data_rows);
           }
           table.setModel(dtm);

           // Create Header For JTable
           TTHeader tth = new TTHeader(table.getColumnModel());
           tth.setToolTipStrings(tooltipsSDB);
           table.setTableHeader(tth); // On This Line I Get NullPointerException With Uknown Source

           table.repaint();
      } catch (SQLException e) {
           JOptionPane.showMessageDialog(null, "Populate table error! \n" + e);

      } 
 }

 public static void main(String args[]) {
      EventQueue.invokeLater(new Runnable() {
           public void run() {
                try {
                     new Table();
                } catch (Exception e) {
                     JOptionPane.showMessageDialog(null, e);
                }
           }
      });
 }

和 TTHeader 类:

String[] toolTips;

public TTHeader(TableColumnModel model) {
    super(model);
}

public String getToolTipText(MouseEvent e) {
    int col = columnAtPoint(e.getPoint());
    int modelCol = getTable().convertColumnIndexToModel(col);
    String retStr;
    try {
        retStr = toolTips[modelCol];
    } catch (NullPointerException ex) {
        retStr = "";
    } catch (ArrayIndexOutOfBoundsException ex) {
        retStr = "";
    }
    if (retStr.length() < 1) {
        retStr = super.getToolTipText(e);
    }
    return retStr;
}

public void setToolTipStrings(String[] toolTips) {
    this.toolTips = toolTips;
}

当我从 JComboBox 中选择第二个数据库时,会出现 NPE。在 JComboBox 监听器中,我调用 populateTable() 方法。这是更具体的堆栈跟踪:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at mypackage.TTHeader.getToolTipText(TTHeader.java:19)
at javax.swing.ToolTipManager$insideTimerAction.actionPerformed(Unknown Source)
at javax.swing.Timer.fireActionPerformed(Unknown Source)
at javax.swing.Timer$DoPostEvent.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$200(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

第 19 行:

int modelCol = getTable().convertColumnIndexToModel(col);

最佳答案

当您获得 NPE 并识别该行时,您首先检查的是取消引用运算符 (.) 的所有出现。此类运算符左侧 (!) 的值将为 null。 (如果一行上有多个 .,则使用其中之一。因此,如果您的行是 foo.getBar().doSomething(),则 foo nullfoo.getBar() 返回 null。但是 doSomething() 返回的是没关系。)

在这种情况下,可能是 getTable() 方法返回 null

自 Java 5 以来,出现了两种新的、更隐蔽的可能 NPE的原因:

  1. for (Foo foo : fooCollection) 中隐式解除引用,如果 fooCollection 为 null,则会得到一个 NPE。
  2. 数字自动拆箱:Integer i = null;整数 j = i + 1;//此处为NPE

这就是您通常需要了解的有关 NPE 调试的全部信息,当然还有更一般的建议,即您应该记录变量值或使用调试器逐步执行代码。

关于java - 为什么 setTableHeader() 方法会抛出 NullPointerException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18986391/

相关文章:

Java:如何在一维数组中存储二维数组

Java函数式接口(interface)自动将第一个参数分配为类?

java - E/libEGL:调用未实现的OpenGL ES API

java - JDialog 没有出现

java - 在 JTextPane 中禁用自动换行

java - 如何强制 JScrollPane 仅垂直滚动?

java - 将对象设置为null以及Java中的程序流程

java - headless (headless)浏览器,对 java 有完整的 javascript 支持

java - 找不到@Getter和@Setter

java - 先决条件库为 notNull 检查抛出 IllegalArgumentException