问题
I am coming back to writing code in Java after a long gap - most of my coding work over the past few years has been in PHP & JavaScript - and am discovering that I have to work harder to satisfy the Java compiler which is far more rigorous about issues such as variable scope and exception handling. A piece of code that caused me some trouble is shown below
File file = new File(path, fname);
FileOutputStream stream = null;
try
{
stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
}
finally
{
try
{
if (null != stream) {stream.close();}
return true;
}
catch(Exception e){return false;}
}
This is accepted by the compiler. However, before I got here I had run into several issues.
- First attempt: No Catch Block. The compiler refused to play ball because it wanted me to deal with the eventuality that the FileOutputStream could not be created. Ditto for writing to that stream. I understand the logic behind this reasoning and like it.
- Second attempt: Catch Block but...:I was declaring and creating the
stream
variable INSIDE thetry
block. The compiler threw a wobbly again - thestream
variable was out-of-scope in thefinally
block.
As you will see I have gotten around the issue by declaring stream
above the try
block and initializing it to null.
This works. However, given just how rusty my Java skills are I thought I would ask: Is there a right way to write such code?
回答1:
The idiomatic way to handle such scenarios in modern Java versions (since Java 7) would be to use a try-with-resource block that handles all the ugly closing "logic" for you. You'd still have to either catch the exception or propagate it upwards, but that's a relatively small issue. Consider the following:
public static boolean writeToFile(String path, String fname) {
File file = new File(path, fname);
try (FileOutputStream stream = new FileOutputStream(file)) {
stream.write(tosave.getBytes());
} catch (IOException e) {
// Should probably log the exception too
return false;
}
return true;
}
回答2:
You could simply use below code snippet:
try (FileOutputStream stream = new FileOutputStream(file)){
stream.write(tosave.getBytes());
}catch(IOException e) {
e.printStackTrace();
return false;
}
return true;
It's a new feature (try-with-resources Statement) introduced in Java 7.
回答3:
I think you're getting hung up on stuff that isn't important. Yes, in some situations coding try/catch/finally IS important because you actually need to do something to fix an error.
But for opening/closing a file, you don't want to get yourself into knots just to satisfy the compiler. Code Readability is much more important.
How about:
String path="somepath";
String fname="somefile";
String tosave="somedata";
try {
File file = new File(path, fname);
FileOutputStream stream = new FileOutputStream(file);
stream.write(tosave.getBytes());
stream.close();
}
catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
回答4:
The "right" way is to use Java 7's try with resources. It has been a long time coming, but it cleans up this sort of boilerplate code really well.
Tough luck if you are stuck on an earlier Java version :)
来源:https://stackoverflow.com/questions/36934061/java-scoping-visibility-rules