ultrabowser ultrabowser - 5 months ago 10
Java Question

When to use a String with filename or File as argument to constructor?

When should I use a

File
and when should I use a
String
with a filename as constructor? The constructed method should contain the contents of the file. So I can choose:

public GraphModel(File file) throws IOException {
this();
readFromFile(file);
}


versus

public GraphModel(String filename) throws IOException {
this();
readFromFile(new File(filename));
}


Is one preferred over the other?

Answer

Some people think this is a matter of taste / personal preference ... or that it doesn't matter. I would argue that it DOES matter.

Lets assume that your API's implementation does require a File internally. Then, there are three alternative approaches:

  // #1
  public GraphModel(File file) throws IOException {...}

  // #2
  public GraphModel(String file) throws IOException {...}

  // #3
  public GraphModel(File file) throws IOException {...}
  public GraphModel(String file) throws IOException {...}

Now compare these APIs in various contexts:

  • If you adopt approach #1, and the caller has the filename as a String it must construct a File. This potentially results in duplicative code1.

  • If you adopt approach #2, and the caller has the filename as a File it must use File.toString() to get the argument for the constructor. This is potentially duplicative AND it is inefficient2.

  • If you adopt approach #3, the API works well in either case.

So my conclusion is:

  • If you are trying to provide a general API for use in contexts where you don't know what form the caller will have the filename, then approach #3 is clearly the best, and approach #2 is better than approach #1.

  • If your API is not general; i.e. you are designing for a specific context, then either approach #1 or #2 could be OK ... if they fit your intended usage patterns. However, you might3 also want to design your application so that you don't keep on creating File objects for the same filenames.


1 - If your constructor is called in lots of places, that could mean a new File(...) call at each place.

2 - The caller must convert its File to a String, only to have your constructor create a new File from the String.

3 - But ONLY if this aspect of the application is demonstrably performance critical.