Gripe with Java

Just came across this idiosyncracy:Shouldn't FileNotFoundException have a constructor that takes a file argument? wouldn't that make the most sense.
[164 byte] By [tjacobs01a] at [2007-11-27 5:08:06]
# 1
Nice one :D
PhHeina at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 2
Why? It doesn't exist. ;-)
bsampieria at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 3
To include failure-capture information? Probably. But this is true for many exceptions in the java api.
YoGeea at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 4

Why? When would you use this constructor? What are you doing to tell you that this file does or does not exist so you have control over the construction of the exception?

Point being that when a FileNotFoundException is thrown it's by something that is out of your control so a constructor of the type you mention would be useless at that point. What would be handy would be the ability to get the file object or the String containing the path and file name that it couldn't load.

Just my 2 krupplenicks on the subject, your milage may of course vary.

PS.

puckstopper31a at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 5

Otherwise, I think the point would be that FNFEx would have a field for the File/path that the users of it would use.

You could always subclass that exception if you are the one generating it, that way you can put the File or path in it.

But of course you could always know what file/path you are using before the method call that might throw that exception and remember if for the catch block to use so you know.

bsampieria at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 6
Maybe the exception is being thown by third party code, and the OP want to do something with the file name.You could always parse the error message, but that's a hack, of course.
Hippolytea at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 7
I have no disagreement with wanting to do something with the file name in the exception, my point is just that at the point at which the exception is being thrown he has no control over it and a constructor that took the file or filename would be useless to him.PS.
puckstopper31a at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 8

> and a constructor that took the file or filename would be useless to him.

You're right. I was reading in between the lines: if you could pass a File to

the constructor, then there's obviously going to be a getFile method.

Then I was going to use ArrayIndexOutOfBoundsException as an example.

It has a constructor that takes an int index, but um, ugh, no getIndex method.

Nevermind ;-(

Hippolytea at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 9

There are a number of things in the api that I find myself scratching my head over. One of them that was only recently changed is why didn't ClassCastException tell you what it was trying to cast and to what? With JDK 1.5 it now reveals that information. Handy wot?

That said, as a rule if I find something in the api that doesn't work the way I think it should, it is generally (not necessarily always) a failure on my part to properly understand rather than a failing on the part of the api.

PS.

puckstopper31a at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 10

> I have no disagreement with wanting to do something

> with the file name in the exception, my point is just

> that at the point at which the exception is being

> thrown he has no control over it and a constructor

> that took the file or filename would be useless to

> him.

Below is the code I'd written. I have commented out the FileNotFoundException I was throwing, letting it throw the exception lower down. I think this solution is fine.

However what if it was the case that there was some serious processing that I wanted to do before opening the file? By not providing a File parameter constructor, is it your opinion that the FileNotFoundException should never be directly instantiated?

public static InfoFetcher loadData(File f) throws FileNotFoundException{

//if (!f.exists()) throw new FileNotFoundException("File not found: " + f.getAbsolutePath());

long len = f.length();

if (len > Integer.MAX_VALUE) {

throw new RuntimeException("File size exceeds maximum size for a byte buffer");

}

return loadData(new BufferedInputStream(new FileInputStream(f)), (int) len, TimeOut.NO_TIMEOUT);

}

tjacobs01a at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 11
No, not at all. You can use FileNotFoundException wherever you need to throw an exception due to a file not being in existence. It's just that the catcher of the exception has to know what file was being looked for if it needs to do something else.
bsampieria at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 12

No, that's actually not what I'm saying. What I'm saying is that most often when the FileNotFoundException is thrown it's down someplace where you don't have control over what's going on. For example, if one is using reflection and executes the following line of code:

Class clazz = Class.forName(classname goes here) ;

the exception is thrown without your control so a constructor that took a filename wouldn't be useful. In your illustration (which is something I likely wouldn't do but that's neither here nor there) is a place where it would be handy to have such a constructor, but the question then becomes would good would it do you to have it. As you've illustrated you have a constructor that takes a String which can just as easily be the path and filename.

PS.

puckstopper31a at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 13

Don't see why it's a big deal to not do this:

File file = ...;

try

{

InfoFetcher info = loadData(file);

... // success

}

catch(FileNotFoundException fnfe)

{

System.err.println("File " + file.getName() + " not found.");

}

bsampieria at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 14

> No, that's actually not what I'm saying. What I'm

> saying is that most often when the

> FileNotFoundException is thrown it's down someplace

> where you don't have control over what's going on.

> For example, if one is using reflection and executes

> the following line of code:

>

> >

> Class clazz = Class.forName(classname goes here) ;

>

>

>

> the exception is thrown without your control so a

> constructor that took a filename wouldn't be useful.

> In your illustration (which is something I likely

> wouldn't do but that's neither here nor there) is a

> place where it would be handy to have such a

> constructor, but the question then becomes would good

> would it do you to have it. As you've illustrated you

> have a constructor that takes a String which can just

> as easily be the path and filename.

>

> PS.

I agree with this assessment as well (not that that's either here nor there ;o).

abillconsla at 2007-7-12 10:27:29 > top of Java-index,Java Essentials,Java Programming...
# 15

> constructor, but the question then becomes would good

> would it do you to have it. As you've illustrated you

> have a constructor that takes a String which can just

> as easily be the path and filename.

Yes. But this would override the default message of the exception. Counting on a FileNotFoundException to contain a message string which is just the file that wasn't found is potentially dangerous.

The way it should be implemented is to just have 1 constructor - taking a File, plus a getter method to get the File that wasn't found. That way, the getMessage() method would be safe as well.

tjacobs01a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 16

And so then when you catch it:

try {

testFile(new File(argv[0]));

}

catch(FileNotFoundException fnfe) {

System.out.println(fnfe);

}

}

What will it print?

abillconsla at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 17

> Yes. But this would override the default message of

> the exception. Counting on a FileNotFoundException to

> contain a message string which is just the file that

> wasn't found is potentially dangerous.

>

> The way it should be implemented is to just have 1

> constructor - taking a File, plus a getter method to

> get the File that wasn't found. That way, the

> getMessage() method would be safe as well.

Dangerous in what way, and what are you gaining by having a file reference to a file that the operating system can't find? What are you hoping to be able to do with it?

PS.

puckstopper31a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 18

The point is that by passing the file into the constructor you can ensure the exception contains the relevant failure-capture information. By passing the file into the constructor you automatically capture all this information rather that relying on the detail message (FileNotFoundException has a private constructor that accepts path and reason but it is only called by native I/O methods). Accessor methods such as getPath() to retrieve the path of the file that could not be found are also useful if you want to programmatically retrieve the details of the exception. This is good practise in general, not specific to FileNotFoundException.

YoGeea at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 19

> Dangerous in what way, and what are you gaining by

> having a file reference to a file that the operating

> system can't find? What are you hoping to be able to

> do with it?

Well, if not found, create it, of course. However it's better to test for existence using the methods provided in the File class than to wait for an exception to be thrown.

bsampieria at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 20
The idea of counting on throwing an exception to decide whether to create a file is terrifying to me. Better to test the File object and use its methods for doing that rather than handing off to an exception handler to do it.PS.
puckstopper31a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 21
Exactly.
bsampieria at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 22

Too, you can only go so far in trying to protect the masses. This is true for life and it is true in programming. Look what a hash Generics are (I know some dissagree here - there's room for all opinions ;o) ... but take a look at COBOL code that was written many years ago and still runs. Why? Certainly NOT because COBOL is fail-safe (it's super easy to crash a COBOL pgm) ... but because companies demanded good coders or else those coders where going to be there fixing it all night when it blew. Don't get me wrong - alot of bad COBOL code was written over the years, I am not saying not.

abillconsla at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 23

> The idea of counting on throwing an exception to

> decide whether to create a file is terrifying to me.

> Better to test the File object and use its methods

> for doing that rather than handing off to an

> exception handler to do it.

We're getting a bit off of my original point, which was simply that FileNotFoundException is IMO incorrectly specified.

tjacobs01a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 24

I think most would agree that, yes, it would be extremely nice (since a File object is not required to have an existing file behind it) if FNFEx would require a way that the exception specify which file was not found.

However, as pointed out, the reason probably stems from the fact that Java's creators went for simplicity in a lot of case, which is why you find this same sort of behavior all over Java.

at least not via the API...

ClassCastException was already mentioned.

NoSuchMethodException doesn't say what method doesn't exist.

IndexOutOfBoundsException doesn't tell you which index.

NumberFormatException doesn't tell you the bad value.

The reason is simple enough in my mind. Your code, going into the method that will throw these exceptions, knows what it's going to input, therefore it should be able to retain that bad value after an exception is caught. Therefore you already know what's the bad value.

bsampieria at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 25
Good point!
tjacobs01a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 26

Another thing to think about is, what is the first thing everyone (almost without exception) offers as the very first piece of advice when someone posts a thread saying anything like, "My program is blowing up and I don't know why."

So, what is the first thing we all jump to? I'll give you a hint it's one word. STACKTRACE ... What's in the stacktrace? The line number where the error is occuring. One can presume that if the problem is one of debugging that the developer will have access to the stack trace which will point to the offending line of code. Hopefully by reading the line of code it should be fairly clear why it's unhappy. Obviously that's not always the case and sometimes can be bloody **** cryptic. If however the problem is not one of debugging but is in fact a case of wanting to take an action then it's actually a different problem and as bsamperi pointed out, there are actually better ways to deal with that occurence.

Also, there is the point of what is an exception and why do we care? An exception is a case outside the normal flow of events in the program. A case where you have a file reference that doesn't exist and you want to do something about it is not outside the normal flow of events it's a branch of the normal flow.

There is also that putting a constructor on the FNFE that takes a File creates a dependency between the FNFE class and the File class. The developers of the api tend to resist such dependencies wherever possible.

Enough ramble,

PS.

puckstopper31a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 27

Stacktrace... don't get me started. Damned obfuscated applet code doesn't give line numbers and only gives cryptic letter method names which I have to dig through the map file and backtrace to figure out if it's method a() or a(String) or a(int). Ratsin-fratsin-mumble-mumble...

Good point about depedencies though. I can see using FNFEx for URI/URL-based files or something else too, which complicates the exception class more.

bsampieria at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 28
bsampieri, Good point about line no's in applets. I've managed to never actually have to implement an applet in anything meaningful. It's one of those things I run screaming from, so I've rarely had occasion to have to debug one.PS.
puckstopper31a at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 29

> What's in the stacktrace? The line number where the error is

> occuring. One can presume that if the problem is one

> of debugging that the developer will have access to

> the stack trace which will point to the offending

> line of code. Hopefully by reading the line of code

> it should be fairly clear why it's unhappy. Obviously

> that's not always the case and sometimes can be

> bloody **** cryptic.

Yes, it can be cryptic, especially if it is an intermittent problem that is not easily reproducible. That is why you you should give as much information as possible. By, for example, passing a File into the FileNotFoundException constructor, or passing lower bound, upper bound and the actual index value to IndexOutOfBoundsException, you are ensuring you capture all the relevant failure information since the exception class can handle this automatically. This is better than relying on the detail message that gets passed into the constructor. I am not suggesting you maintain a reference to the file, merely that you use the file to automatically capture any relevant information.

> Also, there is the point of what is an exception and

> why do we care? An exception is a case outside the

> normal flow of events in the program. A case where

> you have a file reference that doesn't exist and you

> want to do something about it is not outside the

> normal flow of events it's a branch of the normal

> flow.

For checked exceptions the caller should be reasonably expected to recover.

YoGeea at 2007-7-21 21:19:57 > top of Java-index,Java Essentials,Java Programming...
# 30

> Yes, it can be cryptic, especially if it is an

> intermittent problem that is not easily reproducible.

> That is why you you should give as much information

> as possible. By, for example, passing a File into the

> FileNotFoundException constructor, ...

This argument would sit better if you were referring to exceptions that don't need to be caught. IndexOutOfBoundsException does fall into that category, of course.

But you need to catch a FileNotFoundException, so at that point, you should have all the information from before the method throwing it. Not wanting to define variables outside the try block for more compact code shouldn't be a good reason.

But by the same token, NullPointerExceptions never tell me what variable/method call returned the null that I'm trying to access something within. That's where the stack trace should come in, of course, but as mentioned, can be unreliable (particularly with obfuscation). So I declare that NPE should tell me specifically what was null.

bsampieria at 2007-7-21 21:20:02 > top of Java-index,Java Essentials,Java Programming...