繁体   English   中英

有什么方法可以在静态类中使用非静态方法?

[英]Is there any way to use a non-static method in a static class?

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

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

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

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

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

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

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

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

也许吧 ,但不是出于您陈述的原因。 您为什么不想创建类的实例? 如果那是使它静态化的唯一原因,那么它就不是一个非常相关的东西。 确实,诸如Singleton Pattern之类的东西实际上可以实现相同的目的,从而确保您不必继续创建实例,因为始终只使用一个实例。

如果您的对象正是... object ,则应将其建模为实例。 我通常倾向于认为事物是事物的本质上是非静态的,事物是关于事物的概念,本质上是更加静态的。

让我们暂时使用汽车的OO例子。 如果我想知道汽车的价格,那是特定汽车的财产。 我必须指定一个Accord实例,以便查询该属性。 另一方面,如果我想知道特定型号的平均价格,那更多的是静态概念。 我不是在谈论Accord任何特定实例,而只是在说Accord 因此,诸如getPrice()类的东西将是Car的实例方法,而诸如getAveragePrice()类的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();
    }
}

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

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();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM