2

我对 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];
    }
}

所以就像你所看到的......有 2 个不同的类,它们具有相同的方法,但接收不同的数据。我需要从用户那里获取DefFunctionHandler类中“字符串名称”的输入,并用我拥有的文件中的名称来识别给定名称......然后将其与方法中的其他数据相关联,例如funcgroupand func。另一个func班级也是如此。所以我需要对它们进行比较以获取其他类中的数据,例如时间等。

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

4

5 回答 5

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];
    }
}

然后通过创建gettersetter来访问它们:

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

但是,一些建议...

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

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

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()在基类中添加一个抽象方法,因为那个方法应该有相同的签名,并且根本不带参数!


最后结果

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

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();
    }
}
于 2013-06-06T14:51:01.110 回答
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];
        ...
    }
}
于 2013-06-06T14:49:29.197 回答
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;
   } 
}
于 2013-06-06T15:00:03.233 回答
0

您需要重组对象以具有适当的构造函数和设置器/获取器

这提供了保护所有私有变量的好处,并通过仅允许其他类通过那些 setter/getter 和构造函数访问它的内部变量来强制其他类遵守您的类的“合同”。现在您只需实例化对象,然后使用 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);
    }
}
于 2013-06-06T14:54:26.257 回答
-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.在调用单个方法之前创建一个包装方法来进行比较。

希望这对您有所帮助。

于 2013-06-06T14:51:16.083 回答