在2个不同类中的2个方法之间交换数据

时间:2013-06-06 14:39:52

标签: java

我对Java很新,这可能是一个基本的疑问。但请帮忙。 我有一个课程如下:

public class EnterLeaveHandler implements IOtfHandler {
    public void handle(java.lang.Object ... args) {

        long time = (Long) args[0];
        int func = (Integer) args[1];
        int cpuid = (Integer) args[2];
        int source = (Integer) args[3];
}

我有另一个班级:

public class DefFunctionHandler implements IOtfHandler {

    public void handle(Object... args) {

        int stream = (Integer) args[0];
        int func = (Integer) args[1];
        String name = (String) args[2];
        int funcgroup = (Integer) args[3];
        int source = (Integer) args[4];
    }
}

所以你可以看到..有两个不同的类,它们有相同的方法,但接收不同的数据。我需要从用户那里获得DefFunctionHandler类中“String name”的输入,并且我在文件中标识给定的名称,然后将其与方法中的其他数据相关联例如funcgroupfunc。另一个类中也存在相同的func。所以我需要在它们之间进行比较,以获得其他类中的数据,如时间等。

因此,方法中的数据可以与C中的数据结构进行比较......如何在Java中实现这样的结构?我读到结构类似于Java中的类。但在我的情况下,我有方法而不是类的数据。请告诉我如何解决这个问题。

5 个答案:

答案 0 :(得分:3)

回答您的原始问题

简而言之,您无法从外部访问方法变量。您希望做的是在类中添加字段变量。将它们放在方法之外意味着它们会在方法完成后继续存在,这意味着您可以从外部访问它们。

public class EnterLeaveHandler implements IOtfHandler {
    private long time;
    private int func;
    private int cpuid;
    private int source;

    // Please don't use varargs like this; read the whole answer!!
    public void handle(Object ... args) {
        time = (Long) args[0];
        func = (Integer) args[1];
        cpuid = (Integer) args[2];
        source = (Integer) args[3];
    }
}

然后您可以通过创建 getters setters 来访问它们:

public long getTime() {
    return time;
}
public void setTime(long t) {
    time = t;
}
// etc...

然而,一些建议......

你的代码......奇怪,至少可以说。它也非常类似Java。尽可能地,您应该尽量避免使用需要不同数据的多个重写方法。此外,您通常希望在构造函数中初始化字段,而不是在其他方法中。

目前尚不清楚您可以访问多少代码,但如果您能够重写界面,我绝对会这样做。界面中的Object varargs很奇怪。使用接口的原因是您可以使用相同的参数调用接口方法,并且无论下面的对象类型如何,都会发生一些有用的事情。它违背了接口的要点,让同一方法的两个实现需要完全不同的参数。以下代码说明了原因:

IOtfHandler h1 = new EnterLeaveHandler();
IOtfHandler h2 = new DefFunctionHandler();
h1.handle(0, 0, 0, 0);
h2.handle(0, 0, 0, 0); // Crashes with ClassCastException!! :(
                       // And would also crash two lines later with ArrayIndexOutOfBoundsException

好多了让他们完全不同的方法。你知道你期待的变量,所以你应该利用这个事实。看起来像这样的方法签名会好得多:

public class EnterLeaveHandler implements IOtfHandler {
    public void handle(long time, int func, int cpuid, int source) {
    // Do things with your shiny new variables
}
public class DefFunctionHandler implements IOtfHandler {
    public void handle(int stream, int func, String name, int funcgroup, int source) {
        // Do things with your shiny new variables
    }
}

正如其他人所说,如果"真实"方法签名不相同,您不应该使用接口。最好使用抽象基类来保存它们之间常见的小数据:

abstract class IOtfHandler {
    private int source;
    private int func;

    public void setSource(int source) {
        this.source = source;
    }
    // etc
}
class EnterLeaverHandler extends IOtfHandler {
    private long time;
    // etc
}
class DefFunctionHandler extends IOtfHandler {
    private String name;
    // etc
}

当然,如果在构造函数中设置所有变量,则可以向基类添加抽象handle()方法,因为那时该方法应该具有相同的签名,并且不需要参数所有!


最终结果

因此,如果我们将我讨论过的所有更改汇总到一起 - 将方法变量移动到字段,使用 getters setters ,使用有用的方法签名,使用构造函数,并使用基类而不是误导性的接口,我们最终得到这样的东西:

abstract class IOtfHandler {
    private int source;
    private int func;

    public void setSource(int source) {
        this.source = source;
    }
    public int getSource() {
        return source;
    }
    public void setFunc(int func) {
        this.func = func;
    }
    public int getFunc() {
        return func;
    }

    // abstract handle method
    abstract public void handle();
}

class EnterLeaverHandler extends IOtfHandler {
    private long time;
    private int cpuid;

    // getters and setters
    public void setTime(long time) {
        this.time = time;
    }
    public long getTime() {
        return time;
    }
    public void setCpuId(int cpuid) {
        this.cpuid = cpuid;
    }
    public int getCpuId() {
        return cpuid;
    }

    // constructor
    public EnterLeaverHandler(long time, int cpuid, int source, int func) {
        setTime(time);
        setCpuId(cpuid);
        setSource(source);
        setFunc(func);
    }

    // handle method
    public void handle() {
        System.out.println("EnterLeaverHandler.handle()");
        // Do whatever class-specific handling you might want to do in here.
    }
}

class DefFunctionHandler extends IOtfHandler {
    private String name;
    private int funcGroup;
    private int stream;

    // getters and setters
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setFuncGroup(int funcGroup) {
        this.funcGroup = funcGroup;
    }
    public int getFuncGroup() {
        return funcGroup;
    }
    public void setStream(int stream) {
        this.stream = stream;
    }
    public int getStream() {
        return stream;
    }

    // constructor
    public DefFunctionHandler(String name, int funcGroup, int stream, int source, int func) {
        setName(name);
        setFuncGroup(funcGroup);
        setStream(stream);
        setSource(source);
        setFunc(func);
    }

    // handle method
    public void handle() {
        System.out.println("DefFunctionHandler.handle()");
        // Do whatever class-specific handling you might want to do in here.
    }
}

public class Main {
    public static void main(String[] args) {
        IOtfHandler h1 = new DefFunctionHandler("name", 0, 0, 0, 0);
        IOtfHandler h2 = new EnterLeaverHandler(0, 0, 0, 0);
        h1.handle();
        h2.handle();
    }
}

答案 1 :(得分:0)

为了使变量成为类变量,您所要做的就是将它们的声明移到方法之外。换句话说,您的EnterLeaveHandler代码可能如下所示:

public class EnterLeaveHandler implements IOtfHandler {

    long time;
    int func;
    int cpuid;
    int source;

    public void handle(java.lang.Object ... args) {

        time = (Long) args[0];
        func = (Integer) args[1];
        cpuid = (Integer) args[2];
        source = (Integer) args[3];
        ...
    }
}

答案 2 :(得分:0)

您需要重新构建对象以使用适当的构造函数和setter / getters

这样可以保护所有私有变量,并强制其他类遵守classe的“契约”,只允许它们通过setter / getters和constructor访问它的内部变量。现在你只是实例化对象,然后用ti的方法来操作它。

以下是您的第一个示例类的示例:

public class EnterLeaveHandler implements IOtfHandler {

    private long time;
    private int func, cpuid, source;

    public EnterLeavehandler(long time, int func, int cpuid, int source) {

        this.time = time;
        this.func = func;
        this.cpuid = cpuid;
        this.source = souce;

    }

    public long getTime() {
        return this.time;
    }

    public void setTime(long time) {
        this.time = time;
    }

    public int getFunc() {
        return this.func;
    }

    public void setFunc(int func) {
        this.func = func;
    }

    public int getCPUID() {
        return this.cpuid;
    }

    public void setCPUID(int cpuid) {
        this.cpuid = cpuid;
    }

    public int getSource() {
        return this.source;
    }

    public void setSource(int source) {
        this.source = source;
    }

    public void handle(long t, int f, int c, int s) {

        this.setTime(t);
        this.setFunc(f);
        this.setCPUID(c);
        this.setSource(s);
    }
}

答案 3 :(得分:0)

为您的类创建一个抽象超类。使用类扩展它并在句柄调用中初始化参数。

public abstract class AbstarctFunctionHandler implements IOtfHandler { 
   long time; 
   int func; 
   int cpuid; 
   int source 
   //add getters and setters, if you fancy

   public boolean equals(AbstarctFunctionHandler obj){ 
      //compare variables 
      return true;
   } 
}

答案 4 :(得分:-2)

我能想到的最好的解决方案 1.创建一个getter和setter

 public void setName(String name) {
       this.name = name;
    }

    public String getName() {
       return name;
    }

http://docs.oracle.com/javaee/6/tutorial/doc/gjbbp.html

2.在调用单个方法之前,创建一个包装方法来进行比较。

希望这会对你有所帮助。