GUI里的。package gui;//: gui/ButtonGroups.java
// Uses reflection to create groups
// of different types of AbstractButton.
import static net.mindview.util.SwingConsole.run;import java.awt.FlowLayout;
import java.lang.reflect.Constructor;import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToggleButton;
import javax.swing.border.TitledBorder;public class ButtonGroups extends JFrame {
  private static String[] ids = {
    "June", "Ward", "Beaver", "Wally", "Eddie", "Lumpy"
  };
  static JPanel makeBPanel(
    Class<? extends AbstractButton> kind, String[] ids) {
    ButtonGroup bg = new ButtonGroup();
    JPanel jp = new JPanel();
    String title = kind.getName();
    title = title.substring(title.lastIndexOf('.') + 1);
    jp.setBorder(new TitledBorder(title));
    for(String id : ids) {
      AbstractButton ab = new JButton("failed");
      try {
        // Get the dynamic constructor method
        // that takes a String argument:
        Constructor ctor =
          kind.getConstructor(String.class);
        // Create a new object:
        ab = (AbstractButton)ctor.newInstance(id);
      } catch(Exception ex) {
       ex.printStackTrace();
        System.err.println("can't create " + kind);
      }
      bg.add(ab);
      jp.add(ab);
    }
    return jp;
  }
  public ButtonGroups() {
    setLayout(new FlowLayout());
    add(makeBPanel(JButton.class, ids));
    add(makeBPanel(JToggleButton.class, ids));
    add(makeBPanel(JCheckBox.class, ids));
    add(makeBPanel(JRadioButton.class, ids));
    
//
// add(makeBPanel(MetalComboBoxButton.class, ids));
//

    
    add(makeBPanel(JCheckBoxMenuItem.class, ids));
    add(makeBPanel(JMenu.class, ids));
    add(makeBPanel(JRadioButtonMenuItem.class, ids));
  }
  public static void main(String[] args) {
    run(new ButtonGroups(), 500, 350);
  }
} ///:~以上是例子的代码。
其中红色部分是我后来加入的。
但红色部分跑到绿色部分时,抛出NoSuchMethodException异常。请问,
Constructor ctor =
          kind.getConstructor(String.class)
方法的具体作用是什么?
如何判断所用的class是否有getConstructor方法?最好能扩展的讲一讲。~

解决方案 »

  1.   

    但红色部分跑到绿色部分时,抛出NoSuchMethodException异常。 什么意思?
    getConstructor 就是返回这个类的构造函数对象
      

  2.   

    就是说,为什么MetalComboBoxButton.class调用getConstructor(String.class)方法会出错?
    因为MetalComboBoxButton.class没有此方法吗?
      

  3.   

    那是构造函数....是让你创建对象用的...
    你把它设为私有,就不能new他了,还有些别的用处如带几个参数什么的
    不是让你当方法用的...
    构造器再去看下吧
      

  4.   

    这是java的反射机制,可以根据类的名字或者一个对象等信息来获取这个对象的类,构造函数或者实例方法等。
    Constructor ctor = kind.getConstructor(String.class); 
    这个方法返回kind对象的类的一个构造方法,并且此构造方法有一个参数为String类型。此方法返回一个构造器类(Constructor)的对象,你可以用ctor.newInstance()来构造创建该构造方法的声明类的新实例。
    一个class是否有getConstructor方法你不需要进行判断,事实上在java里面一个Class类的对象,就像你代码里面的kind,语法上都是提供getConstructor方法的,所以你也无法通过逻辑控制去判断。而java的解决方法是在没有getConstructor方法时抛出一个异常,你只要跟着抛出或捕获NoSuchMethodException就可以了。
      

  5.   

    NoSuchMethodException:
    说明MetalComboBoxButton这个类没有MetalComboBoxButton(String id){}这样的构造方法,或者该构造方法不是public的.
      

  6.   

    package javax.swing.plaf.metal;import java.awt.*;
    import java.awt.event.*;
    import javax.swing.plaf.basic.*;
    import javax.swing.*;
    import javax.swing.plaf.*;
    import javax.swing.border.*;
    import java.io.Serializable;/**
     * JButton subclass to help out MetalComboBoxUI
     * <p>
     * <strong>Warning:</strong>
     * Serialized objects of this class will not be compatible with
     * future Swing releases. The current serialization support is
     * appropriate for short term storage or RMI between applications running
     * the same version of Swing.  As of 1.4, support for long term storage
     * of all JavaBeans<sup><font size="-2">TM</font></sup>
     * has been added to the <code>java.beans</code> package.
     * Please see {@link java.beans.XMLEncoder}.
     *
     * @see MetalComboBoxButton
     * @version 1.38 12/19/03
     * @author Tom Santos
     */
    public class MetalComboBoxButton extends JButton {
        protected JComboBox comboBox;
        protected JList listBox;
        protected CellRendererPane rendererPane;
        protected Icon comboIcon;
        protected boolean iconOnly = false;    public final JComboBox getComboBox() { return comboBox;}
        public final void setComboBox( JComboBox cb ) { comboBox = cb;}    public final Icon getComboIcon() { return comboIcon;}
        public final void setComboIcon( Icon i ) { comboIcon = i;}    public final boolean isIconOnly() { return iconOnly;}
        public final void setIconOnly( boolean isIconOnly ) { iconOnly = isIconOnly;}    MetalComboBoxButton() {
            super( "" );
            DefaultButtonModel model = new DefaultButtonModel() {
                public void setArmed( boolean armed ) {
                    super.setArmed( isPressed() ? true : armed );
                }
            };
            setModel( model );
        }    public MetalComboBoxButton( JComboBox cb, Icon i, 
                                    CellRendererPane pane, JList list ) {
            this();
            comboBox = cb;
            comboIcon = i;
            rendererPane = pane;
            listBox = list;
            setEnabled( comboBox.isEnabled() );
        }    public MetalComboBoxButton( JComboBox cb, Icon i, boolean onlyIcon,
                                    CellRendererPane pane, JList list ) {
            this( cb, i, pane, list );
            iconOnly = onlyIcon;
        }    public boolean isFocusTraversable() {
    return false;
        }    public void setEnabled(boolean enabled) {
    super.setEnabled(enabled); // Set the background and foreground to the combobox colors.
    if (enabled) {
        setBackground(comboBox.getBackground());
        setForeground(comboBox.getForeground());
    } else {
        setBackground(UIManager.getColor("ComboBox.disabledBackground"));
        setForeground(UIManager.getColor("ComboBox.disabledForeground"));
    }     
        }    public void paintComponent( Graphics g ) {
            boolean leftToRight = MetalUtils.isLeftToRight(comboBox);        // Paint the button as usual
            super.paintComponent( g );        Insets insets = getInsets();        int width = getWidth() - (insets.left + insets.right);
            int height = getHeight() - (insets.top + insets.bottom);        if ( height <= 0 || width <= 0 ) {
                return;
            }        int left = insets.left;
            int top = insets.top;
            int right = left + (width - 1);
            int bottom = top + (height - 1);        int iconWidth = 0;
            int iconLeft = (leftToRight) ? right : left;        // Paint the icon
            if ( comboIcon != null ) {
                iconWidth = comboIcon.getIconWidth();
                int iconHeight = comboIcon.getIconHeight();
                int iconTop = 0;            if ( iconOnly ) {
                    iconLeft = (getWidth() / 2) - (iconWidth / 2);
                    iconTop = (getHeight() / 2) - (iconHeight / 2);
                }
                else {
            if (leftToRight) {
        iconLeft = (left + (width - 1)) - iconWidth;
    }
    else {
        iconLeft = left;
    }
                    iconTop = (top + ((bottom - top) / 2)) - (iconHeight / 2);
                }            comboIcon.paintIcon( this, g, iconLeft, iconTop );            // Paint the focus
                if ( comboBox.hasFocus() && (!MetalLookAndFeel.usingOcean() ||
                                             comboBox.isEditable())) {
                    g.setColor( MetalLookAndFeel.getFocusColor() );
                    g.drawRect( left - 1, top - 1, width + 3, height + 1 );
                }
            }        if (MetalLookAndFeel.usingOcean()) {
                // With Ocean the button only paints the arrow, bail.
                return;
            }        // Let the renderer paint
            if ( ! iconOnly && comboBox != null ) {
                ListCellRenderer renderer = comboBox.getRenderer();
                Component c;
                boolean renderPressed = getModel().isPressed();
                c = renderer.getListCellRendererComponent(listBox,
                                                          comboBox.getSelectedItem(),
                                                          -1,
                                                          renderPressed,
                                                          false);
                c.setFont(rendererPane.getFont());            if ( model.isArmed() && model.isPressed() ) {
                    if ( isOpaque() ) {
                        c.setBackground(UIManager.getColor("Button.select"));
                    }
                    c.setForeground(comboBox.getForeground());
                }
                else if ( !comboBox.isEnabled() ) {
                    if ( isOpaque() ) {
                        c.setBackground(UIManager.getColor("ComboBox.disabledBackground"));
                    }
                    c.setForeground(UIManager.getColor("ComboBox.disabledForeground"));
                }
                else {
                    c.setForeground(comboBox.getForeground());
                    c.setBackground(comboBox.getBackground());
                }
                int cWidth = width - (insets.right + iconWidth);
                
                // Fix for 4238829: should lay out the JPanel.
                boolean shouldValidate = false;
                if (c instanceof JPanel)  {
                    shouldValidate = true;
                }
                
        if (leftToRight) {
            rendererPane.paintComponent( g, c, this, 
         left, top, cWidth, height, shouldValidate );
        }
        else {
            rendererPane.paintComponent( g, c, this, 
         left + iconWidth, top, cWidth, height, shouldValidate );
        }
            }
        }
    }
    这个是类的源码