Catch block variable warning in Java
I try to get my code to compile with no errors and no warnings as standard practice. There is one annoying warning, though, that I know how to deal with in .NET but not in Java. Say I have a code block like this:
try {
FileInputStream in = new FileInputStream(filenam开发者_运维百科e);
return new Scanner(in).useDelimiter("\\A").next();
} catch (FileNotFoundException ex) {
LOG.log(Level.SEVERE, "Unable to load file: {0}", filename);
return null;
}
I get a warning that variable ex
is not used. Now, I don't really have a use for ex
, I don't want ex
, but I don't know what to do about it. In .NET I could just do:
catch (FileNotFoundException)
without the variable and it will compile and run with no error.
How would one handle this situation in Java? I know I could make a local variable and set it to ex
, but that seems like a silly and wasteful workaround to fix a warning that isn't really needed.
Log the exception. It is always useful anyway when chasing a bug.
Use the @SuppressWarnings("unused")
annotation.
See also:
- Annotations tutorial
- Supported Values for @SuppressWarnings
There's no clean way to "mark ex
as used" in Java, except by using it.
Note, however that according to its documentation a FileNotFoundException
can also be thrown when "[...] the file does exist but for some reason is inaccessible, for example when an attempt is made to open a read-only file for writing."
Therefore I suggest you do use the exception by also printing message from the exception.
I'm aware that this doesn't answer the general question, but I can hardly think of an exception of which I wouldn't at least log some information when it happens.
The warning is an IDE warning, you should be able to turn it off.
However, there are many reasons that FileNotFoundException can be thrown, you will want to know the reason in this case.
IntelliJ recognises ignore
or ignored
as a deliberately ignored Exception or a non-empty catch block as acceptable depending on your setting.
Basically, you are SOL (you have to declare the variable and suck up the warning) because JAVA a bit manic-depressive, or at least nanny-ish, in its approach to the developer; this is yet another example. JAVA makes you declare the catch variable even if you never intend to use it. That means you have an unused variable lying around just waiting to cause a problem. While there were a lot of comments about "you need to work with this exception variable", those comments miss the point of the question. The question is "how do I not get this unused variable warning", the example uses FileNotFound exception, but it could be any exception. The question was not about FileNotFound exception, it was about the unused variable warning.
The exception type doesn't matter for this question. For example, I have a class that manages data buffers. It can throw an exception for a few reasons, one of which is the data buffer being full. So, if I try to put data into the full buffer, my function can receive that exception. It is the only exception it can receive in this situation. One function I have that uses this class detects the exception and expands the buffer. It does not care about the exception variable, it does not log the exception, it processes the exception and moves on. Instead of the exception, I could return a flag that indicates that the buffer is full, but the defeats the exception processing system (there are other routines in the system where this exception is an error and I handle them with logging and messages to the user, etc.)
So, I could set the IDE to ignore the unused variable warning. But that is not a good idea because there are times when not using a variable indicates a real problem (I missed a piece of code or maybe I forgot to end a block comment or something). Or, at a minimum, I have a piece of unused code that could add confusion in the future. I could suppress the warning, but that is just a kludge. The bottom line is I have to put in an unused variable, document why it is unused, and kludge a work around to suppress the warning (so QA doesn't complain) all because JAVA wants to protect me from myself.
<rant>
This is where I have a major problem with JAVA. JAVA claims that they are a serious programming language for serious professionals to use on serious projects. Yet, they then make the assumption that these same serious professionals always make stupid mistakes and they need to be protected from those mistakes. It is almost like telling surgeons they can't use a scalpel because they could cut themselves. If you are making a toy programming language for amateurs then put in all the protections you want. But, if you are claiming to make a language for professionals, then give professionals the tools they need to do their job. They are professionals, give them professional tools. Things like forcing the definition of an unused variable, not allowing operator overloads, not having unsigned primitives, and basically treating user classes as second-class citizens limits the tool set and indicates a point of view that professional engineers are not all that professional. I don't mind the warnings - they help the development process go faster. I dislike the lack of a full tool set. That causes work around, kludges, and a whole new source of errors.
Anyway, sorry for the rant
</rant>
You should log the exception. According to the FileInputStream API, a FileNotFoundException
can be thrown "if the file does not exist, is a directory rather than a regular file, or for some other reason cannot be opened for reading." If you encounter that problem, having more detail in your log file (such as the stack trace) will make it easier to fix.
If I compile that code with javac, I don't get a warning, so either you're using a different compiler, or different settings - I assume an IDE is used with special settings for unused variables.
In eclipse I turn such warnings linewise off with annotations, in this case: @SuppressWarnings ("unused")
in the line before.
Almost every time I think I have no use for an exception, one occurs to me after a while. Usually.
If you honestly can't think of anything worthwhile to do with an exception instance, it's time to consider the possibility that you have not identified the correct spot in the program flow at which to handle the exception.
Another possibility, perhaps more likely with exceptions you've written yourself, is that your exception does not provide what you need to recover from the exceptional condition.
And hopefully the least likely possibility is that you're abusing the exception system to do something that ought to be done with another flow control structure, like an if or while block.
I've wondered about that in my Algebraic Integer Calculator project, in which you can (or will be able to) do things like inquire what's the greatest common divisor (GCD) of 8 and 3√2. The answer is of course √2, but the computer needs some kind of algorithm, like the Euclidean algorithm, to figure that out.
So my program divides 8 by 3√2. That causes NotDivisibleException
to be thrown. That exception should provide at least one rounding function by which to round 8/3√2 to an algebraic integer.
Other times, though, I just want to know whether one algebraic integer is divisible by another. For example,
public static boolean isDivisible(AlgebraicInteger a, AlgebraicInteger b) {
try {
a.divides(b);
return true;
} catch (NotDivisibleException nde) {
return false;
} catch (AlgebraicDegreeOverflowException adoe) {
return false;
}
}
As you can imagine, this gives me an unused exception warning. It's the main reason why I wonder if the NotDivisibleException
is an abuse of the exception system.
What's the alternative here? I could rewrite the division function in isDivisible
so that it gives me the true or false without triggering any exceptions.
Therefore, this one unused exception warning is preferable to duplicating the division function almost verbatim.
As for AlgebraicDegreeOverflowException
, I decided that's a runtime exception that should probably be caught by the caller, not by isDivisible
. The adoe
clause is therefore stricken.
So this leaves me with one unused exception warning. I think maybe the best I can do with it is limit it to a single occurrence, by encapsulating it in a function rather than repeating it each time I need to do a simple divisibility test.
In the Scala version of this program, I can use "_
" to indicate I don't actually need the exception object. Or I could even overload the modulo operator so that it can handle AlgebraicInteger
operands, or define an implicit conversion, etc.
But that's Scala. In Java, there are only three options:
- Use the exception in some way
- Suppress the warning
- Ignore the warning
The last two are kind of the same, though.
I am aware that this is a question from eight years ago. I'm curious to know what you decided to do in the case of the FileNotFoundException
.
In your shoes, I think I would have decided to at least log the exception message, after retrieving it with the getMessage()
function. There might be some extra context you couldn't put on here which might suggest a different solution.
精彩评论