繁体   English   中英

如何覆盖类中的 toString 方法

[英]How to override toString method in a class

我正在尝试生成一个 jList 类。

如果我做:

package test;

import javax.swing.DefaultListModel;

public class TestFrame extends javax.swing.JFrame {

    DefaultListModel jList1Model = new DefaultListModel();

    public TestFrame() {

        initComponents();

        jList1Model.addElement(TestClass.class);
        jList1.setModel(jList1Model);

    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList<>();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jList1.setModel(new javax.swing.AbstractListModel<String>() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            public int getSize() { return strings.length; }
            public String getElementAt(int i) { return strings[i]; }
        });
        jScrollPane1.setViewportView(jList1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new TestFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JList<String> jList1;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration                   
}

作为我的TestClass

package test;

public class TestClass {

    public static String name = "Test Class 1";
    public int foo;
    public int bar;


}

然后我得到:

在此处输入图片说明

到现在为止还挺好。

现在我想在 jList1 中显示name class 属性的内容而不是class test.TestClass test.TestClass 。

我试过这个:

public class TestClass {

    public static String name = "Test Class 1";
    public int foo;
    public int bar;

    public static String toString() {
        return name;
    }

}

但我什至无法编译它:

toString() in TestClass cannot override toString() in Object overriding mehtod is static.

不是覆盖toString方法的答案,而是如何让列表显示与toString返回的内容不同的解决方案。 ListCellRenderer添加到列表中。 基本上扩展默认的( JLabel本身的扩展)并更改应显示的内容:

class ClassRenderer extends DefaultListCellRenderer {
    @Override
    public Component getListCellRendererComponent(
            JList<?> list, Object value, int index, boolean selected, boolean focus) {
        if (value instanceof Class) {
            value = ((Class<?>) value).getSimpleName();
        }
        return super.getListCellRendererComponent(list, value, index, selected, focus);
    }
}

要使用它,只需调用(在显示列表之前)

list.setCellrenderer(new ClassRenderer());

更多细节,更好的解释可以在官方教程中找到: 提供自定义渲染器


JB Nizet建议的解决方案(我的解释,希望我理解正确):创建一个对象来保存Class及其标签; 将其实例添加到列表中:

public class LabeledClass {

    private final String label;
    private final Class<?> theClass;

    LabeledClass(String label, Class<?> theClass) {
        this.label = Objects.requireNonNull(label);
        this.theClass = theClass;  // TODO null check?
    }

    public Class<?> getTheClass() {
        return theClass;
    }

    @Override
    public String toString() {
        return label;
    }

    // TOD hashcode, equals ?
}

用作:

model.addElement(new LabeledClass("Test", TestClass.class));

无需为此更改默认单元格渲染器。 优点:如果更改为在您的图表中使用,则更面向对象,非常简单的示例,而不是LabeledClass

public abstract class ChartEnricher {

    private final String name;

    protected ChartEnricher(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public abstract void enrichChart();

    @Override
    public String toString() {
        return name;
    }
}

必须为每个可能的条目实现enrichChart方法,或者有一个通用的方法,该方法使用为其构造函数提供的Class (作为LabeledClass )。 显然,如果需要更多功能,这可以根据用例进行扩展。

以防万一它对某人有帮助,使用原始 OP 的输入,我最终将接受的答案与名为getClassName的静态方法结合起来,该方法通过反射调用。

注意:我已经包含了使用稍微不同的名称但仍然显示反射用法的最终代码。 我的真实应用程序显然比包含的简化 OP 发布示例更复杂,因为它打算使用从抽象类扩展的许多类,这些类强制扩展类来实现多种方法。

附带说明:我唯一没有设法强制执行的是静态getClassName方法的实现,因为显然您不能在 Java 中强制执行静态方法实现(显然抽象静态方法是不可能的)。

class IndicatorsRenderer extends DefaultListCellRenderer {


    @Override
    public Component getListCellRendererComponent(JList<?> list,
                                                   Object value,
                                                   int index,
                                                   boolean isSelected,
                                                   boolean cellHasFocus) {


        Class<? extends BaseIndicator> baseIndicatorClass = ((Class<? extends BaseIndicator>) value);

        try {
            return super.getListCellRendererComponent(list, baseIndicatorClass.getMethod("getClassName").invoke(baseIndicatorClass), index, isSelected, cellHasFocus);
        } catch (NoSuchMethodException ex) {
            Logger.getLogger(IndicatorsRenderer.class.getName()).log(Level.SEVERE, "No such method exception while trying to access Name of indicator. Exception {0}", ex);
            System.exit(1);
        } catch (SecurityException ex) {
            Logger.getLogger(IndicatorsRenderer.class.getName()).log(Level.SEVERE, "Security exception while trying to access Name of indicador. Exception {0}", ex);
            System.exit(1);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(IndicatorsRenderer.class.getName()).log(Level.SEVERE, "Illegal Access Exception while trying to access Name of indicator. Exception {0}", ex);
            System.exit(1);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(IndicatorsRenderer.class.getName()).log(Level.SEVERE, "Illegal Argument Exception while trying to access Name of indicator. Exception {0}", ex);
            System.exit(1);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(IndicatorsRenderer.class.getName()).log(Level.SEVERE, "Invocation Target Exception while trying to access Name of indicator. Exception {0}", ex);
            System.exit(1);
        }

        return null;

     }
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM