【问题标题】:AttributeSet is null, unsure how to fix thisAttributeSet 为空,不确定如何解决此问题
【发布时间】:2019-10-31 04:18:22
【问题描述】:

所以我的问题是由于某种原因我的 AttributeSet 为空,我不确定如何解决这个问题。

public class MyDocumentFilter extends DocumentFilter {

//TODO FIX THIS, as IS NULL FOR SOME REASON

@Override
public void replace(FilterBypass fb, int i, int o, String s, AttributeSet set) throws BadLocationException{
    for(int n = s.length(); n > 0; n--){
        char c = s.charAt(n - 1);
        System.out.println(set);
        if(Character.isAlphabetic(c) || c == ' '){
            super.replace(fb, i, o, String.valueOf(c), set);
        }else{
            JOptionPane.showMessageDialog(null, "Error: Type field must not contain numbers and should be longer than 1 character");
        }
    }
}

@Override
public void remove(FilterBypass fb, int i, int o) throws  BadLocationException{
    super.remove(fb, i, o);
}

public void insertString(FilterBypass fb, int i, String s, AttributeSet set) throws BadLocationException{
    super.insertString(fb, i, s, set);
}

这是我的代码,我基于 stackoverflow 上的另一个答案。(jTextField accept only alphabet and white space)

前几天我可以发誓这可以正常工作,但当我今天给我的程序测试数据时,它开始给我 NullPointerExceptions。我完全不知道为什么我的 AttributeSet 为空,有人可以帮忙吗?

Edit1:好的,现在我不完全确定是我的 AttributeSet 为空。我也不确定 NPE 的来源是否是 .replace() 方法。在另一个类中,我初始化了所有的摆动组件,如果我删除 typeField.setText(null)(typeField 是 jTextArea 的名称),程序就不会再抛出 NPE。现在我更加困惑了。

【问题讨论】:

    标签: java


    【解决方案1】:

    这可能是因为您打印 set 而不是 char c。 您应该查看错误堆栈跟踪以查看抛出了哪一行异常,并尝试找出该行中的哪个对象导致了异常。

    【讨论】:

    • NPE 实际上是在 for 循环中抛出的,我不太确定为什么。任何更多的建议将不胜感激......谢谢......
    • @DominicHenley 跟踪是什么样子的
    • GUI.Formatters.MyDocumentFilter.replace(MyDocumentFilter.java:17) 处的线程“AWT-EventQueue-0”java.lang.NullPointerException 中的异常,这是引发的错误。第 17 行是 for 循环。
    • 因为在第 17 行只有一个方法调用 s.length(),我怀疑这是原因。检查输入字符串s是否为空。
    • 我通过在每次输入字符时打印出 s 的值来检查 String s 的值。果然,它确实显示了正确的值。在这一点上,我很确定 AttributeSet 是空的。
    【解决方案2】:

    传递给此方法的set 很可能为空。

    【讨论】:

    • 是的,我意识到传递的集合是空的。我试图找出背后的原因,因为只要 set 为空,它就会抛出 NPE。
    • 从哪里调用replace 方法?
    • 每次用户在我的 GUI 中的 jTextField 中输入内容时都会调用它。
    • 好的,set 如何获取数据? replace 方法似乎对 set 没有任何作用。
    • 另外,如果您可以发布堆栈跟踪信息也会有所帮助,因为这将准确显示哪个类的哪一行引发了空指针异常
    【解决方案3】:

    您没有打印char,它应该是System.out.println(c); 不是System.out.println(set);

    编辑:如果您调用null 对象的方法,它将抛出NullPointerException。调用方法前检查是否为null

    编辑 1:此测试用例不会抛出 NullPointerException。其他可能导致问题的原因。

    import javax.swing.*;
    import javax.swing.text.AbstractDocument;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter;
    import java.awt.event.ActionEvent;
    
    class Test {
    public static String input = null;
    
    private Test() {
        initComponents();
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(Test::new);
    }
    
    private void initComponents() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
        JTextField jtf = new JTextField();
        ((AbstractDocument) jtf.getDocument()).setDocumentFilter(new MyDocumentFilter());
    
        frame.add(jtf);
    
        jtf.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                input = jtf.getText();
                System.out.println(input);
                }
            });
    
            frame.pack();
            frame.setVisible(true);
        }
    }
    
    class MyDocumentFilter extends DocumentFilter {
        @Override
        public void replace(FilterBypass fb, int i, int o, String s, AttributeSet set) throws BadLocationException{
            for (int n = s.length(); n > 0; n--) {
                char c = s.charAt(n - 1);
                if (Character.isAlphabetic(c) || c == ' ') {
                    super.replace(fb, i, o, String.valueOf(c), set);
                } else {
                    JOptionPane.showMessageDialog(null, "Error: Type field must not contain numbers and should be longer than 1 character");
                }
            }
        }
    
    @Override
    public void remove(FilterBypass fb, int i, int o) throws  BadLocationException {
        super.remove(fb, i, o);
    }
    
    public void insertString(FilterBypass fb, int i, String s, AttributeSet set) throws BadLocationException {
        super.insertString(fb, i, s, set);
    }
    }
    

    编辑 2:清除文本字段的黑客解决方案

    jtf.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    jtf.setText(" "); 
    
                    //Simulated backspace to delete space
                    Robot robot = new Robot();
                    int backspace = KeyEvent.VK_BACK_SPACE;
                    robot.keyPress(backspace);
                    robot.keyRelease(backspace);
                } catch (AWTException ex) {
                    ex.printStackTrace();
                }
            }
        });
    

    【讨论】:

    • 您好,感谢您的回复。我打印出 set 以确保它是否真的设置为空。我删除了那行,它仍然给我一个 NPE。你还有什么想法为什么它可能是空的?
    • 发布测试用例给你 NPE @DominicHenley
    • 对不起,我给出的测试用例来自我程序的 GUI。我将尽我所能解释它。基本上,我的 GUI 接受用户输入,并且有一个字段我想将其限制为仅空格或字母字符。如果在该字段中输入了一个数字,它将显示一条 jOptionPane 消息,告诉他们不要输入数字。 jOptionPane 可以工作,但是当我写信并按 Enter 键(向我的数据库发送查询以添加记录)时,它会抛出我的 MyDocumentFilter 类的 for 循环中引用的 NPE。
    • 这很奇怪,其他可能会产生问题。 @DominicHenley 尝试独立测试文档过滤器组件。我附加了一个测试用例。
    • 好吧,这真的很奇怪。我完全不知所措。在尝试解决这个问题时,我注意到这个 NPE 实际上并没有阻止我的程序执行对我的数据库的查询。它只会阻止我的文本字段被设置为空值。尽管抛出了 NPE,但数据库实际上得到了更新。这告诉我,我的 Database 类实际上传递了正确的参数......这让事情变得更加奇怪......
    猜你喜欢
    • 2012-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多