我正在尝试使用Java实现一个简单的电子表格。它通过控制台上的某些菜单与用户交互,用户可以导入给定文件,其中包含有关要创建的电子表格的一些预先制作的信息(行,列和单元格内容)。 我正在尝试创建一个我称为Parser的静态类,这个类的目标是将导入的每一行分解成小块,然后我可以将正确的方法应用于它们(读取内容所在的单元格)添加了,我想添加什么类型的内容)。
我将Parser设置为静态,因为我想在不需要每次需要时实例化新对象的情况下使用它(这是正确的吗?)。我有一个特定的方法给我带来了麻烦。每当我收到这样的输入时:1;1|=2;3
表示我的单元格1; 1引用单元格2; 3。我告诉解析器返回一个新的Reference(getCell(i,j))。这是因为我的Reference类构造函数接收了一个Cell,但当然java编译器告诉我,我不能在静态类中使用非静态方法,即getCell的情况。
所以我的问题是:有没有办法克服这个问题?在静态类中使用非静态方法的任何方法,还是在尝试读取导入文件时应该实例化一个新的Parser对象?
答案 0 :(得分: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;
}
现在,正如您所说,解析器是一个类,而不仅仅是一个方法。但一般规则仍然适用。 您无法从静态方法引用实例字段,因为该静态方法与任何实例都没有关联!
答案 1 :(得分:1)
我将Parser设为静态,因为我想在不需要每次需要时实例化一个新对象时使用它(这是正确的吗?)。
也许,但不是因为你陈述的原因。你为什么不想创建你的类的实例?如果那是仅使其成为静态的原因,那么它不是一个非常相关的原因。实际上,像Singleton Pattern这样的东西基本上可以实现相同的目的,确保您不必保持创建实例,因为总有一个实例可以使用。
如果你的对象正是......一个对象,那么它应该被建模为一个实例。我通常倾向于认为对象本质上是非静态的,而关于对象的概念本质上更加静态。
让我们暂时使用汽车的OO示例。如果我想知道汽车的价格,那就是特定汽车的财产。我必须指定一个Accord
的实例,以便查询该属性。另一方面,如果我想知道特定模型的平均价格,那更多的是静态概念。我不是在谈论Accord
的任何特定实例,只是Accord
一般。因此getPrice()
之类的内容会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();
}
}
答案 2 :(得分:0)
如果你的静态方法需要访问非静态方法(没有实例化任何东西或直接访问实例),那么必须定义为非静态方法。
答案 3 :(得分: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();
}
}