因此,我希望通过反射从一个其他类中访问一个类的数据成员字段。我无法弄清楚,在通过反射得到数据成员之后,我可以改变字段的值。我不知道如何更好地表达它,所以我会让代码为我说话。
下面是调用按钮的处理程序类。以下是其他课程,我将在旅途中解释其功能。
import java.awt.*;
import java.awt.event.*;
public class SimHandler extends Frame{
public myValveButton but0,but1,but2,but3,but4,but5,but6,but7;
public SimHandler(){
super("Liquer Plant Control Panel");
this.setLayout(null);
this.setFont(new Font("Helvetica", Font.PLAIN, 14));
this.setBackground(Color.black);
but0 = new myValveButton("S1a",100,40,this);
but1 = new myValveButton("S1b",100,140,this);
but2 = new myValveButton("S2a",200,40,this);
but3 = new myValveButton("S2b",200,140,this);
but4 = new myValveButton("S3a",100,240,this);
but5 = new myValveButton("S3b",100,340,this);
but6 = new myValveButton("S4a",200,240,this);
but7 = new myValveButton("S4b",200,340,this);
this.setSize(335,410);
this.setLocation(100,100);
this.setVisible(true);
this.toFront();
this.setResizable(false);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
这实际上是我尝试使用反射来改变Silo实例状态的值的地方。下面是LiqPlantSim和Silo课程。正如您所看到的,状态变量无法以这种方式解决,经过一些谷歌搜索,我无法弄清楚如何使其工作。
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.*;
import java.lang.reflect.Field;
public class myValveButton extends Button{
String label;
public myValveButton(String label,int x,int y,Frame f){
super(label);
this.label = label;
this.addActionListener(new myValveButtonHandler(label));
f.add(this);
this.setBounds(x, y, 35, 30);
}
}
class myValveButtonHandler implements ActionListener{
Field f;
String label;
public myValveButtonHandler(String label){
this.label = label;
}
public void actionPerformed(ActionEvent pushButton){
try {
f = LiqPlantSim.class.getDeclaredField("silo"+label.split("")[1]);
System.out.println(f);
//f.state = "full" //Eclipse says 'state cannot be resolved to a type or is not a field'
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
}
System.out.println(label.split("")[2]);
}
}
这是LiqPlantSim类。
import java.util.HashMap;
import java.util.Map;
public class LiqPlantSim{
public Silo silo1,silo2,silo3,silo4;
public Pipe pipe;
public LiqPlantSim(){
silo1 = new Silo(false,false);
silo2 = new Silo(false,true);
silo3 = new Silo(true,false);
silo4 = new Silo(true,true);
pipe = new Pipe();
}
}
这是Silo Class。
public class Silo {
public boolean mixer,resistance;
public String state,mixerState,resState;
public Silo(boolean mix,boolean res){
mixer = mix;
resistance = res;
state = "empty";
}
}
除了了解如何访问孤岛状态变量之外,我非常感谢有关如何更好地构建我的工作的任何反馈和/或建议,以及我可能犯的任何错误。
答案 0 :(得分:1)
首先,Class#getDeclaredField(String)
会返回Field
个对象,而不是该字段的实际值。要获取该值,必须使用Field#get(Object)
,其中参数是您尝试访问字段的类的实例。在您的代码中,这将是:
LiqPlantSim sim = doSomethingToGetInstance();
f = LiqPlantSim.class.getDeclaredField("siloX");
Silo silo = (Silo) f.get(sim);
这让我想到了下一点:为什么要使用反射?您的答案可能与使用标签获取正确的Silo
有关。您应该*重组LiqPlantSim
以使用数组或List
来解决此问题:
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
public class LiqPlantSim{
private List<Silo> silos;
public Pipe pipe;
public LiqPlantSim(){
silos = new ArrayList<>();
silos.add(new Silo(false,false));
silos.add(new Silo(false,true));
silos.add(new Silo(true,false));
silos.add(new Silo(true,true));
pipe = new Pipe();
}
public Silo getSilo(int index) {
return silos.get(index);
}
//Possibly other methods to access silos
}
(编辑:你应该对SimHandler
中的按钮做同样的事情)
然后,在处理程序中,您可以像这样访问Silo
:
public void actionPerformed(ActionEvent pushButton){
try {
int labelLength = label.length();
int index = Integer.parseInt(label.substring(labelLength - 1, labelLength));
Silo silo = doSomethingToGetLiqPlantSimInstance().getSilo(index);
silo.state = "full" //Note that it is good practice to use private fields and public getters and setters
} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
}
System.out.println(label.split("")[2]);
}
更好的是,在构造函数中获取索引并存储它,这样您就不必每次都重新计算它。
*当然,这只是一个建议
答案 1 :(得分:0)
这:"silo"+label.split("")[1]
将创建String
siloS
。
要从label
变量中获取数字,请尝试:label.substring(1,2)
此外,您无需将Frame f
传递给myValveButton
构造函数,您可以使用SimHandler
直接在this.add(but0)
中将按钮添加到框架中。< / p>
答案 2 :(得分:0)
为什么要在按钮类中实现动作侦听器? ValveButton不应该知道点击它时该怎么做。
相反,您应该在SimHandler类中实现您的动作侦听器。在实例化8个ValveButtons之后,您可以在循环中添加动作侦听器。
无论如何 - 如果你真的需要使用反射寻求解决方案,我会建议使用微小的PrivilegedAccessor框架。虽然建议仅在单元测试中使用它,但在您的情况下可能会有用。