I am new to Java, I read that checked exception get raised during compile time only i.e. program will not compile successfully if there is a checked exception which is not handled or thrown.
If something is preventing a compiler to compile a code, then we could just erase it or recode it in another way so that problem doesn't exist.
For example, if we are trying to open a file which is not there in system, we should not just open it. So why the need to handle/throw these exceptions ?
Your conceptual problem here is that you are conflating what happens at compile time and what happens at runtime; i.e. when the program is compiled by the programmer and when it is run by the user.
At compile time the compiler analyses the program to determine what exceptions could be thrown. For example
public static void main(String[] args) {
FileInputStream fis = new FileInputStream(args[0]); // HERE
}
The FileInputStream(String) constructor is declared as throws IOException. (Look it up.) So the compiler knows that the statement at HERE could throw an IOException. And IOException is a checked exception. (Look it up.)
It doesn't know that it will. It cannot possibly know that it will ... because it doesn't know what args[0] will contain. That is only known at runtime; i.e. when the program is run and the user supplies some command line arguments.
Q: What does checked exception mean here?
Well it means the main method either has to be declared as (for example) throws IOException, or it must catch it in a try-catch statement.
Q: So why is is a checked exception?
Because it was declared that way!
Q: Why was it declared that way?
To force the programmer to do deal with the possibility that the file being opened does not exist, is not readable, and so on. When the program is (eventually) run.
The compiler is saying "do something about this thing that might happen ...".
Just to reiterate. The compiler cannot check that the file exists because it doesn't know what pathname the user is going to provide. And even if it did know, AND it checked1 that the file existed at compile, it couldn't know if the file was going to still exist at runtime, possibly on a completely different machine on a different network ... many years in the future.
1 - This is hypothetical. It doesn't check. It would be pointless.
You shouldn't see exception handling as a problem but as a feature.
Assume exceptions wouldn't exist.
var file = new File("test.txt");
if (!file.exists()) {
file.createNewFile();
}
var writer = new FileWriter(file);
// ...
What could go wrong?
Between the check whether the file exists and opening the reader, the file might have been removed by another thread/process. So even though you created it, it's gone -> you need to somehow lock the file
Your memory is full, hence the file could not be created -> you need to check the result of createNewFile for that.
The file exists, but is a directory.
The file is locked, because another process is writing to it -> You need to check if it is being written to.
This would do it (still assuming no exceptions):
var file = new File("test.txt");
if (!file.exists()) {
if(file.createNewFile()) {
if (!file.isDirectory()) {
if (!isUsed(file)) {
var writer = new FileWriter(file);
// ...
}
}
}
}
This is a lot of code and still doesn't handle the first problem.
Whereas
var file = new File("test.txt");
try {
var writer = new Filewriter(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
is way shorter, clearer, easier to understand.
Also, usually, it is more likely that everything works as supposed that that any of these problems occur. So instead of assuming all the worst and doing multiple checks beforehand, one just assumes the best and if something fails, you look for the reason.
This also impacts the runtime. If you run the no-exception code 1000 times, all these checks will be run a 1000 times, no matter if they fail or not. For the exception-code this is not the case, the might never be run at all.
Checked exception in Java have to be handled, that is why the compiler will complain about and didn't compile the code.
But the exception itselfs will not be raised until runtime, in case it happens.
When you write your code you should just handle properly all your checked exception, so you have to write a try catch block or just return the exception from the method.
If you use some library that raises checked exception you can just handle in one of the 2 ways I have already explained.
But in your code you can choose to use unchecked exceptions.
Those kind of exceptions can be ignored and the compiler will be just fine.
Of course your app will crash if one of those unchecked exception is raised while execution and it is not caught.
But that can be desirable in certain situation, where there is no right way to handle the Exception and it is generally a subclass of Error.
Anyway you should not think about on how to handle the error cases in your code but only Exceptions.
More: Exception class, Error class
Related
I write a simple program that output "123" into "output.txt". I noticed that if I do not add "throws FileNotFoundException", java could not even compile.
If I do not have throw clause console says Unresolved compilation problem. Unhandled exception type FileNotFoundException on main.
public static void main(String[] args) throws FileNotFoundException{
PrintWriter out = new PrintWrite("output.txt");
out.println("123");
out.close();
}
Why do I have to add throw clause, I tried creating a "output.txt" before building it but problem exists.
Does it mean that main method will throw FileNotFoundException but what is function that will handle it?
The compiler telling you that you need to add a throws declaration just means that you have called a method that (can) throw a checked exception. You could, instead, just catch the exception yourself, so that your method can't throw the exception by leaving it unhandled.
public static void main(String[] args) {
try {
PrintWriter out = new PrintWrite("output.txt");
out.println("123");
out.close();
} catch (FileNotFoundException e) {
// do whatever else
}
}
To address your specific questions:
You have to add a throw clause because if you call a method that throws an exception, and you don't catch it, then your method will throw that exception. Creating the "output.txt" file will not help, because that method still might throw (how do you know that it will exist at runtime just because it's there when you compile?).
If the main method throws an exception, the program will crash.
The FileNotFoundException is a checked exception, meaning that you should define how to handle this exception.
There are 2 ways :
Handle the line with a try-catch block
Declare the method using throws, this means that the caller will
have to handle the exception.
In your example, you've decided to declare the main with throws. It means that on exception your program will terminate.
There are 2 kind of exceptions in Java checked and runtime exceptions. Java language requires developer to handle checked exceptions. If a method can throw checked exception that exception has to be declared with throws keyword in method definition.
Yes, main method will throw this exception. Java language specification 11.3 says that if exception is not handled then thread is terminated. And 12.8 says that program terminates when all non daemon thread terminate. So in this case program will simply exit.
Javadoc for PrintWriter reveals to us that PrintWriter tries to create the file but will fail with FileNotFoundException if file with that name cannot be created. Maybe folder is missing write permission or existing file is locked by some other process, like text editor?
Answering your first question.
In Java, there are two types of exceptions:
1) Checked: are the exceptions that are checked at compile time. If some code within a method throws a checked exception, then the method must either handle the exception or it must specify the exception using throws keyword.
Since FileNotFoundException is a subclass of IOException, we can just specify IOException in the throws list and make the above program compiler-error-free.
2) Unchecked: are the exceptions that are not checked at the compiled time. Error and RuntimeException classes are unchecked exceptions
Coming to your second question:
You might think that the public static void main method in Java or the main function in C is the real entry point of your program – but it isn't. All high-level languages (including C) have a language runtime that initializes the program and then transfers control flow to the entry point. In the case of Java, initialization will include:
setting up the JVM
loading required classes
running static initializer blocks.This can execute user-defined code before main is invoked. These blocks aren't supposed to throw exceptions.
There are a variety of ways to implement exception handling, but for the purpose of this question, they all can be viewed as a black box. The important thing however is that the language runtime must always provide an outermost exception handler that catches all exceptions that aren't caught by user code. This exception handler will usually print out a stack trace, shut down the program in an orderly fashion, and exit with an error code. Properly shutting down the program includes destroying the object graph, invoking finalizers, and freeing resources such as memory, file handles, or network connections.
I have a method that writes to a file with a given name. Do I have to test this method and, if so, for what should I test it?
public void record(Object o){
try{
FileWriter fileStream = new FileWriter("data.txt", true);
BufferedWriter out = new BufferedWriter(fileStream);
out.write(o.toString());
out.newLine();
out.close();
} catch (Exception e){
System.err.println("Error: " + e.getMessage());
}
}
Whether you have to test is or not is a question for your project lead. If it's determined you should write some tests, then I would test at least these cases
Happy path (write a good object, check the file contents afterwards)
What happens with a null argument (file exist? what's in it? Does it get closed?)
What happens if the method is called multiple times?
What happens if the file already exists, but is not writeable
The answer to the question "Should I test this?" is always "YES". Now, you might not be able to, or might not know how to, or have the time to, or be allowed to, or want to, but that doesn't change the answer.
Tests are always welcome, but in this case thorough code review might be beneficial. It is hard to write a test that will discover that:
out might not be closed properly, causing file descriptors to leak, i.e. when o.toString() throws an exception
if it throws an exception, the stack trace will get lost (incorrect exception handling)
how should the method behave if the Object o does not override toString() should it care?
A couple more code review suggestions: out.close() should be in a finally block (with its own try/catch), you might want to check the input parameter for sanity, you might want to check if the file already exists and is writable. Also, what happens if o is a String with its own newlines?
This may sound awkward ...
But I didn't understand it.
Why do we have compile-time error and not compile-time exception in java ?
I mean to say that we never say compile-time exception.
We tend to say it as compile-time error.
Is there any specific reason for the same ??
Any suggestions are welcomed....
Thanks !
The reason for this is that an exception is something thrown during execution of a program. Java has a specific type for this, the Exception class.
At compile time, your code is not executing, so it cannot throw an exception. Indeed, it is proper execution of the compiler to find errors in your code - certainly not an exception case!
Exception in java is really different than compile error. We don't have the term compile time exception. Because exception is something happens that you don't expect it to happen. We only have checked and unchecked exception. With checked exception, in compile time, the compiler will force you to catch it, but it is not an error. Don't catch it, you can not compile the program but it is not a compile error.
An error indicates that there is a problem with the program. An exception is a specific construct that interrupts the control flow of the program, and unwinds the stack, capturing information about the state of the stack so that it can be reported.
An exception can be used to indicate an error, but not always. For example:
void startOperation() {
try {
while (someComplexOperationIsOnGoing()) {
checkRestart();
}
}
catch (RestartException re) {
startOperation();
}
}
void checkRestart() {
if (shouldRestart()) {
throw new RestartException();
}
}
This incomplete code sample is meant to show a case where an exception is not an error. This is not always best practice; but it is used in some cases where the intent is to interrupt the control flow deep in the program (such as redirecting the page in a web framework, when responding to an HTTP request) and return control to a higher-up level of the stack. The term exception refers to the mechanism which interrupts the program.
In java, there is an Exception class which encapsulates this behavior. The Error class also interrupts the control flow in the same way as an Exception; but it is reserved only for serious, unrecoverable problems that happen at runtime. It is used, for example, when the JVM runs out of memory and can't create new objects.
Exception is something more of an unexpected flow that can be handled.
Compile time error is more like invalid code..so code doesn't even compile..
Hence term "error" since it denotes more serious problem which has to be fixed.
Compile time errors are the result of the inability of the software to be created as it is instructed. For instance:
String myString = new ButtonEvent();
is a compile time error. While an exception is something that is caught during software processing.
try{
while( file.readNextLine() != file.EOF ){
}
}
catch( UnopenedException ex ){
}
Here, we've made the assumption that the file could be properly opened and had been. The exception is for those "exceptional" cases where opening the file didn't occur.
An exception is the specific name for an error that can be handled within the logic of your software. An error is simply that, a typo or just plain wrong code.
I've been told that there is some overhead in using the Java try-catch mechanism. So, while it is necessary to put methods that throw checked exception within a try block to handle the possible exception, it is good practice performance-wise to limit the size of the try block to contain only those operations that could throw exceptions.
I'm not so sure that this is a sensible conclusion.
Consider the two implementations below of a function that processes a specified text file.
Even if it is true that the first one incurs some unnecessary overhead, I find it much easier to follow. It is less clear where exactly the exceptions come from just from looking at statements, but the comments clearly show which statements are responsible.
The second one is much longer and complicated than the first. In particular, the nice line-reading idiom of the first has to be mangled to fit the readLine call into a try block.
What is the best practice for handling exceptions in a funcion where multiple exceptions could be thrown in its definition?
This one contains all the processing code within the try block:
void processFile(File f)
{
try
{
// construction of FileReader can throw FileNotFoundException
BufferedReader in = new BufferedReader(new FileReader(f));
// call of readLine can throw IOException
String line;
while ((line = in.readLine()) != null)
{
process(line);
}
}
catch (FileNotFoundException ex)
{
handle(ex);
}
catch (IOException ex)
{
handle(ex);
}
}
This one contains only the methods that throw exceptions within try blocks:
void processFile(File f)
{
FileReader reader;
try
{
reader = new FileReader(f);
}
catch (FileNotFoundException ex)
{
handle(ex);
return;
}
BufferedReader in = new BufferedReader(reader);
String line;
while (true)
{
try
{
line = in.readLine();
}
catch (IOException ex)
{
handle(ex);
break;
}
if (line == null)
{
break;
}
process(line);
}
}
The basic premise here is false: the size of a try block makes no difference in performance. Performance is affected by actually raising exceptions at runtime, and that's independent of the size of the try block.
However, keeping try blocks small can lead to better programs.
You might catch exceptions to recover and proceed, or you might catch them simply to report them to the caller (or to a human, via some UI).
In the first case, failures from which you can recover are often very specific, and this leads to smaller try blocks.
In the second case, where an exception is caught so that it can be wrapped by another exception and re-thrown, or displayed to the user, small try blocks mean that you know more precisely which operation failed, and the higher-level context in which that call was made. This allows you to create more specific error reports.
Of course, there are… exceptions (sorry!) to these guidelines. For example, in some cases very specific error reports could be a security problem.
It might be useful to know what effect a try block has on the compiled code. It doesn't change the compiled instructions at all! (Of course, the corresponding catch block does, since it's like any other code.)
A try block creates an entry in the exception table associated with the method. This table has a range of source instructions counters, an exception type, and a destination instruction. When an exception is raised, this table is examined to see if there is an entry with a matching type, and a range that includes the instruction that raised the exception. If it does, execution branches to the corresponding destination number.
The important thing to realize is that this table isn't consulted (and has no effect on running performance) unless it's needed. (Neglecting a little overhead in the loading of the class.)
I've been told that there is some overhead in using the Java try-catch mechanism.
Absolutely. And there's overhead to method calls, too. But you shouldn't put all your code in one method.
Not to toot the premature optimization horn, but the focus should be on ease of reading, organization, etc. Language constructs rarely impact performance as much as system organization and choice of algorithms.
To me, the first is easiest to read.
No. The only thing that you should be considering is where you can reasonably handle the exception and what resources you need to reclaim (with finally).
This is premature optimization at its worst. Don't do it.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" - Knuth.
there is very very little benefit to the 2nd method. after all if you can successfully open a file but not read from it, then there is something very wrong with your computer. thus knowing that the io exception came from the readLine() method is very rarely useful. also as you know, different exceptions are thrown for different problems anyway (FileNotFoundException, etc)
as long as you scope it with a 'logical' block, ie opening, reading, and closing a file in 1 go, i would go with the first method. it's much simpler to read and, especially when dealing with IO, the processor cycles used by the try-catch overhead would be minimal if any.
Putting the try blocks around the specific code that may throw an exception, makes it, in my opinion easier to read. You're likely to want to display a different message for each error and provide instructions to the user, which will be different depending on where the error occurs.
However, the performance issue that most people refer to is related to raising the exception, not to the try block itself.
In other words, as long as you never have an error raised, the try block won't noticeably affect performance. You shouldn't consider a try block just another flow control construct and raise an error to branch through your code. That's what you want to avoid.
The second method will generate a compiler error that reader may not have been initialized. You can get around that by initializing it to null, but that just means you could get an NPE, and there's no advantage to that.
I'm writing a test for a piece of code that has an IOException catch in it that I'm trying to cover. The try/catch looks something like this:
try {
oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
} catch (IOException e) {
LOGGER.error("Bad news!", e);
} finally {
The easiest way seems to make FileOutputStream throw a FileNotFoundException, but perhaps I'm going about this all the wrong way.
Anyone out there have any tips?
You could set cacheFileName to an invalid name or to one you know doesn't exist.
From your comment:
Yes, I suppose the question should
really have been "How do I create a
file that does not exist on both Linux
and Windows?" On windows, I can use
'new File("X:/")', where X: is a drive
letter that does not exist. On Linux,
this does not work because that is a
valid file name.
Look at java.io.File.createTempFile. Use it to create the file and then delete it.
Probably pass it something like:
File tempFile;
tempFile = createTempFile(getClass().getName(),
Long.toString(System.currentTimeMillis());
tempFile.delete();
That should give you a unique name in a platform indendent manner that you can safely use without (much) fear of it existing.
There are two parts to any test: getting it to happen and measuring that you got the correct result.
Fault Injection
The easiest answer is the one that's already been mentioned, which is to set cacheFileName to a file that will never exist. This is likely the most practical answer in this situation.
However, to cause an arbitrary condition such as an IOException, what you really want is Fault Injection. This forces faults in your code without forcing you to instrument your source code. Here are a few methods for doing this:
Mock objects You could use a factory method to create an overridden ObjectOutputStream or FileOutputStream. In test code the implementation would throw an IOException when you wanted to, and in production code would not modify the normal behavior.
Dependency Injection In order to get your Mock Object in the right place you could use a framework such as Spring or Seam to "inject" the appropriate object into the class that's doing the work. You can see that these frameworks even have a priority for objects that will be injected, so that during unit testing you can override the production objects with test objects.
Aspect Oriented Programming Instead of changing the structure of your code at all, you can use AOP to inject the fault in the right place. For instance, using AspectJ you could define a Pointcut where you wanted the exception to be thrown from, and have the Advice throw the desired exception.
There are other answers to fault injection on Java; for instance a product called AProbe pioneered what could be called AOP in C long ago, and they also have a Java product.
Validation
Getting the exception thrown is a good start, but you also have to validate that you got the right result. Assuming that the code sample you have there is correct, you want to validate that you logged that exception. Someone above mentioned using a Mock object for your logger, which is a viable option. You can also use AOP here to catch the call to the logger.
I assume that the logger is log4j; to solve a similar problem, I implemented my own log4j appender which captures log4j output: I specifically capture only ERROR and FATAL, which are likely to be the interesting log messages in such a case. The appender is referenced in log4j.xml and is activated during the test run to capture error log output. This is essentially a mock object, but I didn't have to restructure all my code that got a log4j Logger.
I'm writing a test for a piece of code
that has an IOException catch in it
that I'm trying to cover.
I'm not entirely sure I understand your goal, but if you want to test if the exception is thrown, you can tell the test you expect it to throw the exception:
#Test(expected=IOException.class)
Your test will then fail if the exception is not thrown, and succeed if it is thrown (like, if the cacheFileName file does not exist).
A FileNotFoundException would obviously trigger the catch. The javadoc states the cases where it will be thrown.
You should also consider that the ObjectOutputStream constructor can throw an IOException so may want to cover this case in your tests.
Two easy ways would be either set cacheFileName to a non-existent file or set the specified file to read-only access.
-John
As the code is currently written, you could try to mock out the error() call on the LOGGER object and check to see if it gets called when you expect an IOException.
Your desire to test may have uncovered a fundamental problem with the code as it's written. An error is occurring but there's no boolean or flag value (set the filename to a special pattern) that provides other sections of code to determine if writing to the file was successful. If this is contained in a function, maybe you could return a boolean or set an object level variable.
cacheFileName = "thisFileShouldNeverExistAndIfItDoesYouAreScrewingUpMyTests";
Sure you could take steps and jump thru hoops to programatically make sure that the file name will never, ever, ever exist, or you could use a String that will never exist in 99.99999% of cases.
I hope this is what you meant.
if(new File(cachedFile).exists()) {
oos = new ObjectOutputStream(new FileOutputStream(cacheFileName));
//do your code here
} else {
throw new FileNotFoundException("File doesn't exist!");
}