簡體   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