我必须这样做:我有一个JTextField和按钮。当我写入该文本字段时,输出必须在 JLabel 中显示结果。
- 要求用户提供类的名称。
- 使用 Class.forName() 访问 Java Reflection API。
- 使用默认构造函数创建类的新实例(即对象)。
- 查找并显示窗体中类的所有字段,包括继承的字段:
field_type field_name: (field_value(JTextField))(Set(Button))
field_value必须是文本框,以便用户可以通过按"设置"按钮来更改值。 必须将新值更新为对象。 如果字段包含复杂类型(对象、集合等)的值,则不应创建文本框和"设置"按钮。
- 查找并显示类的所有方法,包括继承的方法:return_type method_name (param_type1 (param_value1(JTextField)), param_type2(param_value2(JTextField)) , ..)(调用(按钮))
如果方法具有复杂类型(对象、集合等)的参数,则仅显示参数的类型,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 在下面一行中显示它:类 cs = 类.forName(text);
如果在异常发生之前测试文本字符串,例如通过打印它:
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)
您将看到文本字符串为空,""
.这是因为调用Class cs = Class.forName(text);
时没有文本,因为它是在呈现 GUI 之前调用的,更不用说让用户有时间输入文本了。仅在由于某种类型的用户生成的事件(如 ActionListener 的 actionPerforming 方法)而调用的代码中调用此函数。
换句话说,将关键代码添加到您自己的声明中声明应该添加代码的位置:
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// THIS CODE IS EXECUTED WHEN RETURN IS TYPED // *********!!!!
}
});
我支持您应该显示有关异常的任何和所有信息的评论。请不要让我们猜测问题是什么。
编辑
此外,在匿名内部侦听器类中使用局部变量(包括 JLabels和 JTextField)时会遇到问题。解决此问题的最简单和最好的方法是将需要在此侦听器中访问的变量设为私有类字段。因此,从构造函数中删除它们的声明,而是将它们移动到类本身。
这真的是错误还是"黄线"? Class
是参数化类型,如果不使用泛型,则 Eclipse 将显示警告。
要消除此类警告,只需执行
Class<?> cs = Class.forName(text);
通配符是可以的,因为你真的不知道要加载哪种"类型"的类。