首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Java访问另一个类的数据成员字段

用Java访问另一个类的数据成员字段
EN

Stack Overflow用户
提问于 2015-02-07 11:39:05
回答 3查看 203关注 0票数 0

因此,我希望通过反射从另一个类访问一个类的数据成员字段。我一直无法弄清楚,在通过反射获得数据成员之后,如何更改字段的值。我真的不知道如何更好地表达它,所以我会让代码为我说话。

下面是调用按钮的处理程序类。下面是其余的类,我将对其功能进行解释。

代码语言:javascript
复制
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类。正如您所看到的,状态变量不能以这种方式解析,在进行了相当多的googling搜索之后,我不知道如何使它工作。

代码语言:javascript
复制
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类。

代码语言:javascript
复制
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();          
    }
}

这是筒仓班。

代码语言:javascript
复制
public class Silo {

    public boolean mixer,resistance;
    public String state,mixerState,resState;
    public Silo(boolean mix,boolean res){
        mixer = mix;
        resistance = res;
        state = "empty";
    }

}

除了了解如何访问筒仓的状态变量之外,我还希望得到任何反馈和/或建议,说明如何更好地组织工作,以及我可能犯的任何错误。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-07 12:25:50

首先,Class#getDeclaredField(String)返回一个Field对象,而不是该字段的实际值。要获得值,必须使用Field#get(Object),其中参数是要访问字段的类的实例。在您的代码中,这将是:

代码语言:javascript
复制
LiqPlantSim sim = doSomethingToGetInstance();
f = LiqPlantSim.class.getDeclaredField("siloX");
Silo silo = (Silo) f.get(sim);

这就引出了我的下一个观点:为什么要使用反射?您的答案可能与使用标签获得正确的Silo有关。您应该*重组LiqPlantSim以使用数组或List来解决这个问题:

代码语言:javascript
复制
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

代码语言:javascript
复制
 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
EN

Stack Overflow用户

发布于 2015-02-07 12:02:38

这是:"silo"+label.split("")[1]将创建String siloS。要从label变量try:label.substring(1,2)获得数字

另外,您不需要将Frame f传递给myValveButton构造函数,您可以使用this.add(but0)将按钮直接添加到SimHandler中。

票数 0
EN

Stack Overflow用户

发布于 2015-02-07 12:04:16

为什么要在按钮类中实现操作侦听器?ValveButton不应该知道当它被点击时该做什么。

相反,您应该在SimHandler类中实现动作侦听器。实例化8 ValveButtons之后,可以在循环中添加动作侦听器。

无论如何,如果您真的需要使用反射解决方案,我将使用微小的PrivilegedAccessor框架进行重新注释。虽然建议只在单元测试中使用,但它在您的情况下可能是有用的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28381668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档