aspose file tools*
The moose likes Java in General and the fly likes File's mkdir() method does not throw an exception? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "File Watch "File New topic
Author

File's mkdir() method does not throw an exception?

Marcus Jastrebowski
Ranch Hand

Joined: Nov 15, 2007
Posts: 55
Does anybody know why the File's mkdir() method does not throw an exception? For example:
The creation of a physical directory seems to me a "risky" operation, just as the creation of a physical file is. So I wonder why DOESN'T mkdir() throw a checked IOException? Any ideas?

Thanks,
Marcus
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14150
    
  18

It does return a boolean that tells you if the directory was created or not. It's a matter of design choice, and the designers of the java.io.File class chose to do it this way.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Marcus Jastrebowski
Ranch Hand

Joined: Nov 15, 2007
Posts: 55
Great! Thank you.
Kelvin Chenhao Lim
Ranch Hand

Joined: Oct 20, 2007
Posts: 513
As Jesper said, this is a design question that really has no right or wrong answer.

But I suspect that the reason for the Java API designers' choice was that they didn't want to introduce a checked exception for a method call where a "failure" often doesn't really indicate an exceptional circumstance. It's very common to write code where you want to ensure that a directory exists, so you'd normally just go ahead and issue the mkdir() call no matter what, and silently ignore any false return values. In this very common use case, if mkdir did declare a checked exception, then you'll find that a lot of programmers will just write "catch (IOException e) {}", since they don't really care whether the mkdir operation succeeded. Since that's the case, you may as well forgo the checked exception entirely.

In general, the design principle here is that exceptions should really indicate exceptional circumstances. If a method declares an exception that actually gets thrown pretty frequently for common inputs, then you really should consider whether it's better to indicate that outcome using a return value instead.

In my experience, the Java API designers have done a good job of adhering to this design principle. The closest thing to a violation I can think of would be the number parsing functions, i.e. Double.parseDouble(), Integer.parseInt(), etc. For many common uses (e.g. form input validation), you'd expect these methods to fail quite frequently, so the failure isn't really an exceptional condition--yet they throw a NumberFormatException when that happens. However, this is a bit of a special case, because these methods are defined to return primitive values, and you can't really assign an error code (e.g. null) to a primitive return value. So this is close to a design principle violation, but not quite. On the other hand, if these methods returned objects, then I would consider it a violation to make them throw NumberFormatException.

Hopefully the example above helps to illustrate my point.


Edit: actually, it just occurred to me that Double.valueOf(), Integer.valueOf() etc do return objects, and yet they do throw NumberFormatException. So I'd consider them to be violations of this design principle. But this is just my personal opinion, of course. Like I said at the beginning, there are ultimately no real right or wrong design choices (unless the method doesn't work at all!).
[ November 27, 2007: Message edited by: Kelvin Lim ]

SCJP 5.0
Marcus Jastrebowski
Ranch Hand

Joined: Nov 15, 2007
Posts: 55
I see. That's a very interesting explanation. Thanks Kelvin.

The reason I asked the question in the first place is because it seems to me that the File methods createNewFile() and mkdir are quite similar in their basic principle, functionality, and general outcome. One makes the file, and the other makes the directory -- both of them return boolean value -- but one throws IOException, the other does not. So intuitively, it seemed to me that the design parallelism was violated when considering these 2 methods only...

Then of course, I do not know enough at this stage to second-guess the Java API gods. So if that's the way it is, then that's the way it's gotta be, and we shall learn to live with it.
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
I moved this to Java in General - Intermediate because I don't think it's really appropriate for Programmer Certification. Maybe it should have been moved to the IO forum instead, but Kelvin's reply involves other more general issues, so I thought JiG Intermediate was best.

I tend to agree with Marcus rather than Kelvin here. Even if we just look at IO classes and methods, Java's designers were fairly inconsistent here. There are plenty of methods that return IOException for reasons that are no more unusual than the reasons a call to mkdir() might fail - FileNotFoundException being the most common example. And in my experience, the methods that throw an exception are far more useful, because (a) an exception is harder to overlook, and (b) the exception can contain useful information about what went wrong. Sadly, many Java exceptions still do a poor job of the latter, giving incomplete information - but at least they usually give more information than merely returning false and leaving the developer to wonder what went wrong.

[Kelvin]: In this very common use case, if mkdir did declare a checked exception, then you'll find that a lot of programmers will just write "catch (IOException e) {}", since they don't really care whether the mkdir operation succeeded.

Frankly, in most cases those developers should be beaten severely. In a few cases there may be legitimate reasons to not care, but it's much more common that this is just laziness on someone's part, and it will typically lead to more confusing errors later. ("Why can't I create a file in that directory?", and somewhat later, "Oh, because the directory doesn't exist, because my previous mkdir() call failed and I didn't notice.")

I think an ideal solution would have been to offer two versions of these methods, one which throws an exception, and one which returns a boolean:

This is patterned after FileChannel's locK() and tryLock(). I think this is a good general approach. Sadly, it's not what Java's IO designers did in general. But we can add static utility methods of our own to implement this similarly - look at FileUtils from Jakarta Commons IO. The forceMkdir() method throws an exception, as an alternative to File's mkdir() which returns a boolean.

[Marcus]: Then of course, I do not know enough at this stage to second-guess the Java API gods.

Oh, I think it sounds like you do. Many of Java's classes, particularly the classes present in the earliest releases of the language, were developed in a bit of a rush by different people who weren't always consistent in the decisions they made - in my opinion, anyway. It's not really unusual to find things that could have been designed better. But we don't always agree on what a better design would have been, which partly explains why a better diesign wasn't used in the first place. But I wouldn't be too intimidated by the "Java gods" here, as in many cases they had (and have) very human limitations.


"I'm not back." - Bill Harding, Twister
Marcus Jastrebowski
Ranch Hand

Joined: Nov 15, 2007
Posts: 55
Hi Jim, thank you for contributing your view to the conversation. I appreciate it.

While studying and reviewing for SCJP, I often find myself pondering slightly deeper meaning of why-things-are-the-way-they-are in Java; which occasionally puts me at odds with the scope of the SCJP forum. I guess this question is one of those mind-drifts.

Regarding these 2 File methods (createNewFile() and mkdir()), I think I'd agree with you that some project manager at Sun (no offense to all the project managers out there!) rushed the product to the market a little prematurely. Sun must have been really cranking out and pushing at the maximum speed of production in the very early, prehistoric days of Java. Perhaps the software design review did not identify the potential inconsistencies. (Or maybe they skipped the review in this case!) This little "oopsie-daisy" went out into the world, and it has become the "final word" to live by. Many years later now, it would be way too controversial to deprecate any of these 2 popular methods in the next Java version -- they are used everywhere.

But no matter. To me, Java is still the coolest programming language, with amazing community of programmers standing behind it, and so I shall accept a few minor flaws of character here and there.

Regarding the "Java API gods", I was using the term facetiously of course. The good people at Sun are probably just like any other overworked, quirky software geeks one might spot at a Star Trek Convention in Las Vegas. Just like us, I guess. (... OK, not like you or I... I'm speaking about some other developer that I know...)

Thanks,
Marcus
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: File's mkdir() method does not throw an exception?