0

我正在尝试使用 Java 实现一个简单的电子表格。它通过控制台上的一些菜单与用户交互,用户可以导入给定文件,其中包含一些关于要创建的电子表格的预制信息(行、列和单元格的内容)。我正在尝试创建一个名为 Parser 的静态类,该类的目标是将导入的每一行分解为小块,以便我可以对它们应用正确的方法(读取内容所在的单元格添加,以及我要添加什么类型的内容)。

我将 Parser 设为静态,因为我想使用它而不需要在每次需要时都实例化一个新对象(这是正确的吗?)。不过,我有一个给我带来麻烦的特定方法。每当我收到这样的输入时:1;1|=2;3这意味着我的单元格 1;1 引用了单元格 2;3。我告诉解析器返回一个新的参考(getCell(i,j))。这是因为我的 Reference 类构造函数接收到一个 Cell,但当然 java 编译器告诉我我不能在该静态类中使用非静态方法,getCell 就是这种情况。

所以我的问题是:有没有办法克服这个问题?有什么方法可以在静态类中使用非静态方法,还是在尝试读取导入文件时实例化一个新的 Parser 对象?

4

4 回答 4

2

查看您的一些代码以确定哪种方法更合适可能会有所帮助,但由于这是面向对象设计中的常见缺陷,我将尝试笼统地回答这个问题。

如果您将某些东西定义为静态,这意味着它与任何实例都没有关联,即使它共享类名。例如,

public class Table {
  List<Cell> cells;

  public Table() {
    while (someCondition)
      parseInput(nextInput);
  }

  public Cell getCell(int i, int j) {
    ...
  }

  public static Cell parseInput(String input) {
    Cell cellToReturn = new Cell();
    ...
    if (input.references(cell)) cell = getCell(i,j); //Error here!
    ...
    return cellToReturn;
  }
}

出现问题是因为 parseInput 方法是静态的,但它引用的是特定实例的单元格列表!它引用的是哪一个?谁知道!

您可以通过两种方式解决问题:

1:使解析器非静态:public Cell parseInput(String input) {

2:将表传递给解析器,因此它知道要引用什么:

public static Cell parseInput(String input, Table target) {
  Cell cellToReturn = new Cell();
  ...
  if (input.references(cell)) cell = target.getCell(i,j); //No more error!
  ...
  return cellToReturn;
}

现在,正如您所说,解析器是一个类,而不仅仅是一个方法。但一般规则仍然适用。您不能从静态方法引用实例字段,因为该静态方法不与任何实例关联!

于 2013-11-14T20:55:43.170 回答
1

我将 Parser 设为静态,因为我想使用它而不需要在每次需要时都实例化一个新对象(这是正确的吗?)。

也许,但不是因为你说的原因。你为什么不想创建你的类的一个实例?如果这是您将其设为静态的唯一原因,那么这不是一个非常相关的原因。事实上,像单例模式这样的东西本质上实现了同样的事情,确保您不必继续创建实例,因为总是有一个实例可以使用。

如果您的对象正是……一个对象,那么它可能应该被建模为一个实例。我通常倾向于认为作为对象的事物本质上是非静态的,而作为对象概念的事物本质上更静态。

让我们暂时使用汽车的 OO 示例。如果我想知道汽车的价格,那是特定汽车的财产。我必须指定一个例如的实例Accord才能查询该属性。另一方面,如果我想知道特定型号的平均价格,那更像是一个静态概念。我不是在谈论 s 的任何特定实例Accord,只是Accord在一般情况下谈论 s。因此,类似的东西getPrice()是 on 的实例方法Car,类似的东西getAveragePrice()可能不是。

当我尝试读取导入文件时,我应该实例化一个新的 Parser 对象吗?

那是一件坏事吗?


现在,对于手头的问题,编译器具体抱怨的是哪个参考?我想我很难想象它,你能提供一个简化的代码示例,以便我可以看到这些静态和非静态类/成员之间的关系吗?本质上,您可以从静态位置引用实例成员,您只需要引用一个实例即可。以我上面的例子为例,我不能这样做:

class Car {
    int getPrice() {
        return 20000;
    }

    static int getAveragePrice() {
        return Car.getPrice();
    }
}

但我可以做到这一点(尽管在这个过度做作的例子中可能不明智):

class Car {
    int getPrice() {
        return 20000;
    }

    static int getAveragePrice() {
        var someRandomCar = new Car();
        return someRandomCar.getPrice();
    }
}
于 2013-11-14T20:54:29.880 回答
0

如果您的静态方法需要访问非静态方法(无需实例化任何内容或直接访问实例),则必须将其定义为非静态。

于 2013-11-14T20:45:04.793 回答
0
private static Parser INSTANCE = new Parser();

public static Parser getInstance() {
   return INSTANCE;
}
...

public void nonStaticMethod() {
    Parser parser = Parser.getInstance();
    parser.whateverParserMethodYouWant();
}

编辑以使这一点更清楚:

class Parser {
    private Parser() {}
    private static Parser INSTANCE = new Parser();

    public static Parser getInstance() {
       return INSTANCE;
    }
}
...
class ParserClient {
...    
    public void nonStaticMethod() {
        Parser parser = Parser.getInstance();
        parser.whateverParserMethodYouWant();
    }
}
于 2013-11-14T20:57:13.687 回答