Due to my company's policy of using Eclipse and using Eclipse's code-autofix, the following code pattern appears excessively in the codebase:
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error
}
}
}
IMO it's extremely fugly and hard to read, especially the portion within the finally block (is there really a need to catch 2 instances of IOException?). Is there anyway to streamline the code such that it looks cleaner?
Why do anything? It's working code. It's correct.
Leave it be.
First, about using IOUtils - may worth a shot telling your supervisors that the very application-server / Java runtime environment they might use, uses IOUtils and similar libraries itself. so in essence you're not introducing new components to your architecture.
Second, no, not really. There isn't really any way around it other than writing your own utility that will immitate IOUtils' closeQuietly method.
public class Util {
public static void closeStream(inputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// log something
}
}
}
Now your code is
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
Util.closeStream(is);
}
Not a lot else to do as the IOException in the catch might have some specific processing.
See this question, use the closeQuietly() solution.
InputStream is = null;
try {
is = url.openConnection().getInputStream();
// .....
} catch (IOException e) {
// handle error
} finally {
IoUtils.closeQuietly(is);
}
// stolen from the cited question above
public class IoUtils {
public static closeQuietly (Closeable closeable) {
try {
closeable.close();
} catch (IOException logAndContinue) {
...
}
}
}
Or wait for JDK7's ARM blocks.
You could define something like this somewhere:
private static interface InputStreamCallback {
public void doIt(InputStream is) throws IOException;
}
private void with(InputStreamCallback cb) {
InputStream is = null;
// Creational code. Possibly adding an argument
try {
cb.doIt(is);
} catch (IOException e) {
// handle error or rethrow.
// If rethrow add throws to method spec.
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// handle error or rethrow.
}
}
}
}
And invoke your code like this:
with(new InputStreamCallback() {
#Override
public void doIt(InputStream is) throws IOException {
is = url.openConnection().getInputStream();
// .....
}
});
If you declare with method static in a helper class, then you could even do an import static of it.
There's a drawback. You need to declare url final.
EDIT: creational code is not the point. You can arrange it in several ways. The callback is the point. You could isolate what you need to do there.
Related
I have try and catch block in JAVA code
import java.io.FileOutputStream;
import java.util.zip.ZipOutputStream;
public class TryTest {
public static void main(String[] args) {
String zipPath ="D:/test";
try (ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipPath))){
String Hello ="Hello";
System.out.println("==============>"+Hello);
}catch (Exception e) {
e.printStackTrace();
}
}
}
And my compiled class look like
/*
* Decompiled with CFR 0.145.
*/
....
try {
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(string));){
String string2 = "Hello";
System.out.println("==============>" + string2);
}
....
I wounder why another try block added in compile time.
Full Source code in
https://github.com/vikram06/java_try_catch_bug
This is explained in the JLS 14.20.3.2 Extended try-with-resources :
The meaning of an extended try-with-resources statement:
try ResourceSpecification
Block
Catchesopt
Finallyopt
is given by the following translation to a basic try-with-resources
statement (ยง14.20.3.1) nested inside a try-catch or try-finally or
try-catch-finally statement:
try {
try ResourceSpecification
Block
}
Catchesopt
Finallyopt
The effect of the translation is to put the ResourceSpecification
"inside" the try statement. This allows a catch clause of an extended
try-with-resources statement to catch an exception due to the
automatic initialization or closing of any resource.
Furthermore, all resources will have been closed (or attempted to be
closed) by the time the finally block is executed, in keeping with the
intent of the finally keyword.
When you're using try with resources (I mean try (...) {... ) then Java compiler generates additional code section to display the stacktrace from local variable of type Throwable. That's because Java compiler is decomposing try with resources statement into separate tries - one for closing the resource and another for statements inside your try.
How is it displayed after decompilation - it depends on the decompiler you use.
Author of CFR here - short answer - CFR's 'resugaring' isn't perfect ;) (though the decompiled code is entirely correct, and valid.)
If you find something like this, feel free to submit a bug/improvement.
For what it's worth - the ACTUAL bytecode bears much less of a resemblance to the input - try using cfr with the arguments
--tryresources false --decodefinally false
And you get the unsugared code, which is much closer to the actual bytecode.
public static void main(String[] args) {
String zipPath = "D:/test";
try {
ZipOutputStream zipOut;
block11 : {
zipOut = new ZipOutputStream(new FileOutputStream(zipPath));
Throwable throwable = null;
try {
String Hello2332 = "Hello";
System.out.println("==============>" + Hello2332);
if (zipOut == null) return;
if (throwable == null) break block11;
}
catch (Throwable Hello2332) {
try {
throwable = Hello2332;
throw Hello2332;
}
catch (Throwable throwable2) {
if (zipOut == null) throw throwable2;
if (throwable == null) {
zipOut.close();
throw throwable2;
}
try {
zipOut.close();
throw throwable2;
}
catch (Throwable throwable3) {
throwable.addSuppressed(throwable3);
throw throwable2;
}
}
}
try {
zipOut.close();
return;
}
catch (Throwable Hello2332) {
throwable.addSuppressed(Hello2332);
return;
}
}
zipOut.close();
return;
}
catch (Exception e) {
e.printStackTrace();
}
}
Is it any possible way there to write catch block inside a method and call it from finally when an exception occured in try block
Ex:
try
{
int a=0,b=0;
a=b/0;
}
finally
{
callExceptions();
}
}
public static void callExceptions()
{
catch(Exception e)
{
System.out.println(e);
}
}
catch block must follow a try block. It can't stand alone.
And finally block are made to be after the catch.
You wrote an alone catch inside a finally. That doesn't make sense.
The easiest solution is to pass the exception to the method as a parameter:
public static myMethod() {
try
{
int a=0,b=0;
a=b/0;
}
catch (Exception e)
{
callExceptions(e);
}
finally
{
// do what ever you want or remove this block
}
}
public static void callExceptions(Exception e)
{
System.out.println(e);
}
Ways to uses try/catch/finally
1.- when you want to try to use some method, if everything goes well, will continue else one exception will be thrown on catch block.
try {
// some method or logic that might throw some exception.
} catch (ExceptionType name) {
// catch the exception that was thrown.
}
2.- It's the same the first but adding finally block means that the finally block will always be executed independently if some unexpected exception occurs.
try {
// some method or logic that might throw some exception.
} catch (ExceptionType name) {
// catch the exception that was thrown.
} finally {
// some logic after try or catch blocks.
}
3.- try and finally blocks are used to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. For example:
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
Referencias Official documentation JAVA for try/catch/finally blocks
On your case:
public static myMethod() {
try {
int a=0,b=0;
a=b/0;
} catch (Exception e) {
callException(e);
}
}
public static void callException(Exception e) {
System.out.println(e);
}
This was too long for a comment so sorry it's not a direct answer to your question (as others have pointed out, that's not possible). Assuming what you're trying to do is define a common way to handle your exception logic in one place, Callable might be a way to go. Something like the following might suffice... Although I'm not going to comment on whether any of it is a good idea...
static E callAndHandle(final Callable<E> callable) {
try {
return callable.call();
} catch (final Exception ex) {
System.out.println(ex);
return null;
}
}
static void tryIt() {
final String result = callAndHandle(() -> {
// Thing which might throw an Exception
return "ok";
});
// result == null => there was an error here...
}
Unfortunately Runnable doesn't declare any Exception in the signature, so if you know it always needs to be void and you don't like the return null; or similar hacks, you'd have to define your own interface to pass in.
What the way do close Reader, InputStream, and others using Optional or the Java 8+ features (lambdas ?).
Since years, I'm using the following code that works, but does a better way exists that needs less lines to write with Java 8+ ?
EDIT : I can't use try-with-resources in my case.
private Reader reader;
// Time to close the reader
if (this.reader != null) {
try {
this.reader.close();
}
catch(IOException e) {
LOGGER.warn(e.getMessage(), e);
}
this.reader = null;
}
Regards,
there is try with resources
try(Reader reader = new StringReader(str)){
//code
}catch(Exception e) {
e.printStackTrace();
}
you don't need to close reader
just use try with resources
try (// resources that need to be close) {
//code
} catch (Exception e) {
//code
}
I don't know a compact form in stock Java, which is why I've previously used IOUtils. (Now I always use try-with-resources.)
// Time to close the reader.
IOUtils.closeQuietly(reader);
Note that in the current release this is deprecated in favor of try-with-resources, but you've implied that won't work for you.
Maybe something like this?
private Reader reader;
private void workWithReader() {
this.reader = ... ; // init
// ... do some work with it ...
// close
close(this.reader, e -> LOGGER.warn(e.getMessage(), e));
}
// this can be reused for all Closeables, not only Reader and InputStream
public static void close(Closeable closeable, Consumer<IOException> exceptionHandler) {
if (closeable != null) {
try {
closeable.close();
}
catch(IOException e) {
exceptionHandler.accept(e);
}
}
}
I'm a beginner still, and currently learning about handling exceptions. The exercise in my book I'm trying to figure out tells me to add a Finally block to close out the file I opened, and I don't understand what I'm doing wrong. Keep in mind the file name and path are fake but here is what I have:
public static String readLineWithFinally()
{
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = new RandomAccessFile("products.ran", "r");
try
{
String s = in.readLine();
return s;
}
catch (IOException e)
{
System.out.println(e.toString());
return null;
}
finally
{
try
{
in.close();
}
catch (Exception e)
{
System.out.println("Generic Error Message");
}
}
}
To add on to Taylor Hx's answer, you can take advantage of Java 7's try-with-resources construct to avoid having to use finally altogether in your case.
public static String readLineWithFinally() {
System.out.println("Starting readLineWithFinally method.");
try (RandomAccessFile in = new RandomAccessFile("products.ran", "r")) {
return in.readLine();
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
You'll also want to be certain that your usage is consistent with what the API mandates for RandomAccessFile.
The code that you posted shouldn't compile, as RandomFile(String, String) can possibly throw FileNotFoundException. As such, we must include it in the try block.
System.out.println("Starting readLineWithFinally method.");
RandomAccessFile in = null;
try {
in = new RandomAccessFile("products.ran", "r");
String s = in.readLine();
return s;
} catch (IOException e) {
System.out.println(e.toString());
return null;
} finally {
try {
if(in != null) {
in.close();
}
} catch (Exception e) {
System.out.println("Generic Error Message");
}
}
Keep in mind the file name and path are fake but here is what I have:
That is why you will have a FileNotFoundException while creating RandomAccessFile("products.ran", "r") with read access mode "r".
From the documentation: RandomAccessFile(String name, String mode)
This constructor throws a FileNotFoundException if the mode is
"r" but the given string does not denote an existing regular file,
or if the mode begins with "rw" but the given string does not denote
an existing, writable regular file and a new regular file of that name
cannot be created, or if some other error occurs while opening or
creating the file
Basically, I want to open a file, read some bytes, and then close the file. This is what I came up with:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
try
{
// ...
inputStream.read(buffer);
// ...
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
try
{
inputStream.close();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Maybe I'm spoiled by RAII, but there must be a better way to do this in Java, right?
If you have the same exception handling code for IOException and FileNotFoundException then you can rewrite your example in a more compact way with only one catch clause:
try {
InputStream input = new BufferedInputStream(new FileInputStream(file));
try {
// ...
input.read(buffer);
// ...
}
finally {
input.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
You can even get rid of the outer try-catch if you can propagate the exception which probably makes more sense then manually printing the stack trace. If you don't catch some exception in your program you'll get stack trace printed for you automatically.
Also the need to manually close the stream will be addressed in Java 7 with automatic resource management.
With automatic resource management and exception propagation the code reduces to the following:
try (InputStream input = new BufferedInputStream(new FileInputStream(file))) {
// ...
input.read(buffer);
// ...
}
Usually these methods are wrapped up in libraries. Unless you want to write at this level, it is best to create your own helper methods or use existing ones like FileUtils.
String fileAsString = Fileutils.readFileToString(filename);
// OR
for(String line: FileUtils.readLines(filename)) {
// do something with each line.
}
I don't know if it is the right way, but you can have all your code in the same try block, and then have the different catch blocks right after each other.
try {
...
}
catch (SomeException e) {
...
}
catch (OtherException e) {
...
}
If you want to do this in plain Java, the code you have posted looks OK.
You could use 3rd party libraries such as Commons IO, in which you would need to write much less code. e.g.
Check out Commons IO at:
http://commons.apache.org/io/description.html
Sometimes you can reduce the code to the following:
public void foo(String name) throws IOException {
InputStream in = null;
try {
in = new FileInputStream(name);
in.read();
// whatever
} finally {
if(in != null) {
in.close();
}
}
}
Of course this means the caller of foo has to handle the IOException but this should be the case most of the time anyway. In the end you don't really reduce all that much complexity but the code becomes much more readable due to less nested exception handlers.
My take on this without using utilities would be:
InputStream inputStream = null;
try {
inputStream = new BufferedInputStream(new FileInputStream(file));
// ...
inputStream.read(buffer);
// ...
} catch (IOException e) {
e.printStackTrace();
throw e; // Rethrow if you cannot handle the exception
} finally {
if (inputStream != null) {
inputStream.close();
}
}
Not a one-liner, but not pretty bad. Using, say, Apache Commons IO it would be:
//...
buffer = FileUtils.readFileToByteArray(file);
//...
The thing to rembember is that standard Java lacks many of these little utilities and easy to use interfaces that everyone needs, so you have to rely on some support libraries like Apache Commons, Google Guava, ... in your projects, (or implement your own utility classes).
Use org.apache.commons.io.FileUtils.readFileToByteArray(File) or something similar from that package. It still throws IOException but it deals with cleaning up for you.
Try the following:
try
{
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024];
try
{
// ...
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
//Process the chunk of bytes read
}
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
inputStream.close();
}
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
Google guava has tried to address this problem by introducing Closeables.
Otherwise you have to wait until AutoCloseable from JDK 7 comes out as it addresses some of the cases when IOException is thrown.