0

私はこれをしなければなりません:私は1つのJTextFieldとボタンを持っています。そして、そのTextFieldに書き込むとき、出力はJLabelに結果を表示する必要があります。

  1. クラスの名前を入力するようにユーザーに求めます。
  2. Class.forName()を使用して、JavaReflectionAPIにアクセスします。
  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

例外が発生する前にテキスト String をテストする場合 (たとえば、出力することによって):

  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)

テキスト文字列が空であることがわかります""。これは、GUI がレンダリングされる前に が呼び出されたため、 を呼び出したときにテキストがなくClass cs = Class.forName(text);、ユーザーにテキストを入力する時間を与えないためです。これは、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);

ロードするクラスの「タイプ」が本当にわからないため、ワイルドカードは問題ありません。

于 2013-02-02T18:31:10.240 に答える