0

我必须这样做:我有一个 JTextField 和按钮。当我写入该 TextField 输出时,必须在 JLabel 中显示结果。

  1. 要求用户提供类的名称。
  2. 使用 Class.forName() 来访问 Java 反射 API。
  3. 使用默认构造函数创建类的新实例(即对象)。
  4. 在表单中查找并显示类的所有字段,包括继承的字段:

field_type field_name: (field_value(JTextField))(Set(Button))

field_value 必须是一个文本框,以便用户可以通过按“设置”按钮来更改值。新值必须更新为对象。如果字段包含复杂类型(对象、集合等)的值,则不应创建文本框和“设置”按钮。

  1. 查找并显示类的所有方法,包括继承的方法:return_type method_name (param_type1 (param_value1(JTextField)), param_type2(param_value2(JTextField)) , ..) (Invoke(Button))

如果方法具有复杂类型的参数(对象、集合等),则仅显示参数的类型,跳过 param_values 的文本框和“调用”按钮。当用户按下“调用”按钮时,应用程序必须调用该方法。确保如果该方法更改了字段的值,这些更改会显示出来。

我的代码在这里:

     import java.awt.FlowLayout;
     import java.awt.event.ActionEvent;
     import java.awt.event.ActionListener;
     import java.lang.reflect.Constructor;
     import java.lang.reflect.Field;
     import java.lang.reflect.InvocationTargetException;
     import java.lang.reflect.Method;
     import java.lang.StringBuffer;
     import java.util.Scanner;
     import javax.swing.JButton;
     import javax.swing.JFrame;
     import javax.swing.JLabel;
     import javax.swing.JPanel;
     import javax.swing.JTextField;

     public class ReflectionTest {

private String class_name = "java.lang.StringBuffer";

public ReflectionTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{
    JLabel jl1 = null, jl2, jl3, jl4;
    JFrame jf = new JFrame("New");
    JPanel jp = new JPanel();
     JTextField jtf = new JTextField(20);
     JButton jb = new JButton("Press");
     jtf.setVisible(true);
     jp.add(jb);
     jp.add(jtf);

     jf.add(jp);
     jf.setVisible(true);
     jf.setSize(400, 550);
     jf.setResizable(false);


     String text = jtf.getText().toString();

     Class cs = Class.forName(text);

     jb.addActionListener(
                new ActionListener() {
                    public void actionPerformed(ActionEvent e) {
                         // THIS CODE IS EXECUTED WHEN RETURN IS TYPED
                    }
                }
            );

    for(Constructor c: cs.getConstructors()){
        for(Class p: c.getParameterTypes())
            System.out.print(p.getName()+" ");
        System.out.println();
    }

    Constructor c = cs.getConstructor(new Class[]{String.class});
    Object list = c.newInstance("AA");


    Field pub_fields[] = cs.getFields();
    Field all_fields[] = cs.getDeclaredFields();
    System.out.println("Public fields:");
    for(Field f:pub_fields){

        //Showing public fields
        System.out.println();
        jl1 = new JLabel(f.getType().getName() + " " + f.getName());
        jp.add(jl1);
        jl1.setVisible(true);
                }
    System.out.println("All declared fields:");
    for(Field f:all_fields){

        //Showing all declared fields

        jl2 = new JLabel(f.getType().getName() + " "+f.getName()+" ");
        jp.add(jl2);
        jl2.setVisible(true);

        f.setAccessible(true);
        Object val = f.get(list);
        if (val != null){
            //System.out.println(val.toString());
            jl3 = new JLabel(val.toString());
            jp.add(jl3);
            jl3.setVisible(true);
            System.out.println();
            }
        else{
            System.out.println("NULL");
        //f.get(list1);
    }
    }

}

/**
 * @param args
 * @throws ClassNotFoundException 
 */
public static void main(String[] args) {
    try{
    // TODO Auto-generated method stub
        new ReflectionTest();
    }
    catch (Exception e){
        e.printStackTrace();
    }
}
  }

我有错误。Eclipse 在这一行中显示它: Class cs = Class.forName(text);

4

2 回答 2

3

如果您在异常发生之前测试文本字符串,例如通过打印出来:

  System.out.printf("text = \"%s\"%n", text);
  Class cs = Class.forName(text);

返回:

text = ""
java.lang.ClassNotFoundException: 
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at pkg.ReflectionTest.<init>(ReflectionTest.java:42)
    at pkg.ReflectionTest.main(ReflectionTest.java:102)

您会看到文本 String 为空,"". 这是因为您在调用时没有文本,Class cs = Class.forName(text);因为它是在呈现 GUI 之前被调用的,更不用说给用户输入文本的时间了。仅在由于用户生成的某种事件(例如 ActionListener 的 actionPerformed 方法)而调用的代码中调用它。

换句话说,将关键代码添加到您自己的评论中您声明应该添加代码的位置:

  jb.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
        // THIS CODE IS EXECUTED WHEN RETURN IS TYPED  // *********!!!!
     }
  });

我支持您应该显示有关异常的所有信息的评论。请不要让我们猜测问题是什么。

编辑
此外,在匿名内部侦听器类中使用局部变量(包括 JLabels 和 JTextField)时会遇到问题。解决这个问题的最简单和最好的方法是让需要在这个监听器私有类字段中访问的变量。因此,从构造函数中删除它们的声明,而是将它们移动到类本身。

于 2013-02-02T18:31:19.220 回答
2

真的是错误还是“黄线”?Class是参数化类型,如果您不使用泛型,则 eclipse 将显示警告。

要消除这样的警告,只需执行

Class<?> cs = Class.forName(text);

通配符是可以的,因为你真的不知道你要加载哪个“类型”的 Class。

于 2013-02-02T18:31:10.240 回答