简体   繁体   中英

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

I'm trying to implement a simple spreadsheet using Java. It interacts with the user through some menus on the console, and a user can import a given file with some pre-made info about the spreadsheet to be created (lines, columns, and content of cells). I am trying to make a static class which I called Parser, and the goal of this class is to break down each line of the import into little pieces so I can then apply the correct methods to them (read the cell to which content is being added, and what type of content am I trying to add).

I made my Parser static, because I want to use it without the need of instantiating a new object every time I need it (is this correct?). I have a specific method that is giving me trouble though. Whenever I receive input like this: 1;1|=2;3 it means that my cell 1;1 references the cell 2;3. I am telling the parser to return a new Reference(getCell(i,j)). This is because my Reference class constructor receives a Cell, but of course the java compiler tells me I cannot use a non-static method, which is the case of the getCell, inside that static class.

So my question is: is there any way to overcome this problem? Any way to use a non-static method in a static class or should I instantiate a new Parser object when I try to read an import file?

It might be helpful to see some of your code to determine which method is more appropriate, but as this is a common pitfall in object oriented design, I'll try to answer the question generically.

If you define something as static, that means it has no association with any instances, even though it shares the class name. For instance,

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

The problem arises because the parseInput method is static, and yet it is referencing a specific instance's list of cells! Which one is it referencing? Who knows!

You can solve the issue two ways:

1: Make the parser non-static: public Cell parseInput(String input) {

2: Pass the table to the parser, so it knows what to reference:

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

Now, as you stated, the parser is a class, not just a method. But the general rule still applies. You cannot reference an instance field from a static method, because that static method is not associated with any instance!

I made my Parser static, because I want to use it without the need of instantiating a new object every time I need it (is this correct?).

Maybe , but not for the reason you state. Why don't you want to create an instance of your class? If that's your only reason for making it static, then it's not a very relevant one. Indeed, something like the Singleton Pattern essentially achieves the same thing, ensuring that you don't have to keep creating an instance, because there's always exactly one instance to use.

If your object is exactly that... an object , then it should probably be modeled as an instance. I generally tend to think of things which are objects as non-static by nature and things which are concepts about an object are more static by nature.

Let's use the belabored OO example of cars for a moment. If I want to know the price of a car, that's a property of a particular car. I'd have to specify an instance of an Accord for example in order to query it for that property. If, on the other hand, I want to know the average price for a particular model, that's more of a static concept. I'm not talking about any particular instance of Accord , just Accord s in general. So where something like getPrice() would be an instance method on Car , something like getAveragePrice() might not.

should I instantiate a new Parser object when I try to read an import file?

Is that such a bad thing?


Now, for the problem at hand, which reference specifically is the compiler complaining about? I guess I'm having trouble picturing it, can you provide a simplified code example so I can see how these static and non-static classes/members relate? Essentially you can reference instance members from a static location, you just need to reference an instance in order to do it. Taking my belabored example above, I can't do this:

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

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

But I can do this (albeit probably ill-advised in this overly-contrived example):

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

Editing to make this more clear:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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