This is a simplified class that describes my problem:
public class Main {
enum Test{
First(method()){ // Unhandled exception type Exception
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
}
Above someCondition depends on device and some situations and I can not decide in about it now, also as you can see, I do not want to catch Exception in method.
Yes. It is a compilation error.
No. There is no special syntax to deal with this.
I do not want to catch Exception in method.
Unfortunately if you throw a checked exception, it has to be caught further up the call stack. That is a fundamental design principal for the Java language, and one that the compiler enforces strictly.
In this, case there is no way to catch the checked exception. Hence, if you are going to call a method in enum constant parameter (as per your code), the method cannot throw a checked exception1.
Here is a possible workaround, though this is probably a bad idea:
public class Main {
enum Test{
First(methodCatchingException()){
// ...
};
Test(Object obj){
//...
}
}
static Object method() throws Exception{
// ...
if (someCondition){
throw new Exception();
}
}
static Object methodCatchingException() {
try {
return method();
} catch (Exception ex) {
throw new SomeRuntimeException("the sky is falling!", ex);
}
}
}
Another way to look at this problem is to ask yourself what should happen with the exception if the compiler let you write that ... and an exception was thrown? Where would it go?
You can't catch it ... because the enum initialization is like a static initialization.
If the Java runtime completely ignored the thrown exception, that would be really bad.
If the Java runtime crashed, then the model of checked exceptions is broken.
So, what this is saying to me is that the Java language design is right, the Java compiler is right ... and the real problem here is in your application design:
You should not be propagating a checked exception here. If an exception occurs in this context it is categorically NOT a recoverable error.
Maybe it is inadvisable to use an enum for this ... because of the potential for non-recoverable initialization errors.
(Note that if this method call terminates due to an unchecked exception, it will turn it into an ExceptionInInitializerError. In addition, the JVM will mark the enum class as uninitializable, and will throw an NoClassDefFoundError if your application attempts to use it; e.g. via Class.forName(...).)
I assume that Exception is used here for illustration purposes. It is a bad thing to declare methods as throws Exception or to throw new Exception(...)
1 - I had a look at the JLS for something to back this up. As far as I can tell, the spec does not mention this situation. I'd have expected to see it listed in JLS 11.2.3. However, it is clear that a compiler cannot allow a checked exception to propagate at that point as it would "break" the model of how checked exceptions work.
I don't think you want to be throwing a checked exception here (which is what Exception is). The reason: you're invoking the call of method inside of the constructor of Test. There's really not a clean way to deal with it.
While the obvious choice here is to switch to RuntimeException, I want you to reconsider throwing the exception in the first place. Since your enum will only ever have First declared in it, does it really make sense for it to throw an exception when it's being instantiated? Personally, I don't think it does; whatever dangerous operation it's doing should be deferred until you want to invoke it, and then would you want to throw your exception.
Related
New Java programmers frequently encounter errors phrased like this:
"error: unreported exception <XXX>; must be caught or declared to be thrown"
where XXX is the name of some exception class.
Please explain:
What the compilation error message is saying,
the Java concepts behind this error, and
how to fix it.
First things first. This a compilation error not a exception. You should see it at compile time.
If you see it in a runtime exception message, that's probably because you are running some code with compilation errors in it. Go back and fix the compilation errors. Then find and set the setting in your IDE that prevents it generating ".class" files for source code with compilation errors. (Save yourself future pain.)
The short answer to the question is:
The error message is saying that the statement with this error is throwing (or propagating) a checked exception, and the exception (the XXX) is not being dealt with properly.
The solution is to deal with the exception by either:
catching and handling it with a try ... catch statement, or
declaring that the enclosing method or constructor throws it1.
1 - There are some edge-cases where you can't do that. Read the rest of the answer!
Checked versus unchecked exceptions
In Java, exceptions are represented by classes that descend from the java.lang.Throwable class. Exceptions are divided into two categories:
Checked exceptions are Throwable, and Exception and its subclasses, apart from RuntimeException and its subclasses.
Unchecked exceptions are all other exceptions; i.e. Error and its subclasses, and RuntimeException and its subclasses.
(In the above, "subclasses" includes by direct and indirect subclasses.)
The distinction between checked and unchecked exceptions is that checked exceptions must be "dealt with" within the enclosing method or constructor that they occur, but unchecked exceptions need not be dealt with.
(Q: How do you know if an exception is checked or not? A: Find the javadoc for the exception's class, and look at its parent classes.)
How do you deal with a (checked) exception
From the Java language perspective, there are two ways to deal with an exception that will "satisfy" the compiler:
You can catch the exception in a try ... catch statement. For example:
public void doThings() {
try {
// do some things
if (someFlag) {
throw new IOException("cannot read something");
}
// do more things
} catch (IOException ex) {
// deal with it <<<=== HERE
}
}
In the above, we put the statement that throws the (checked) IOException in the body of the try. Then we wrote a catch clause to catch the exception. (We could catch a superclass of IOException ... but in this case that would be Exception and catching Exception is a bad idea.)
You can declare that the enclosing method or constructor throws the exception
public void doThings() throws IOException {
// do some things
if (someFlag) {
throw new IOException("cannot read something");
}
// do more things
}
In the above we have declared that doThings() throws IOException. That means that any code that calls the doThings() method has to deal with the exception. In short, we are passing the problem of dealing with the exception to the caller.
Which of these things is the correct thing to do?
It depends on the context. However, a general principle is that you should deal with exceptions at a level in the code where you are able to deal with them appropriately. And that in turn depends on what the exception handling code is going to do (at HERE). Can it recover? Can it abandon the current request? Should it halt the application?
Solving the problem
To recap. The compilation error means that:
your code has thrown a checked exception, or called some method or constructor that throws the checked exception, and
it has not dealt with the exception by catching it or by declaring it as required by the Java language.
Your solution process should be:
Understand what the exception means, and why it could be thrown.
Based on 1, decide on the correct way to deal with it.
Based on 2, make the relevant changes to your code.
Example: throwing and catching in the same method
Consider the following example from this Q&A
public class Main {
static void t() throws IllegalAccessException {
try {
throw new IllegalAccessException("demo");
} catch (IllegalAccessException e){
System.out.println(e);
}
}
public static void main(String[] args){
t();
System.out.println("hello");
}
}
If you have been following what we have said so far, you will realise that the t() will give the "unreported exception" compilation error. In this case, the mistake is that t has been declared as throws IllegalAccessException. In fact the exception does not propagate, because it has been caught within the method that threw it.
The fix in this example will be to remove the throws IllegalAccessException.
The mini-lesson here is that throws IllegalAccessException is the method saying that the caller should expect the exception to propagate. It doesn't actually mean that it will propagate. And the flip-side is that if you don't expect the exception to propagate (e.g. because it wasn't thrown, or because it was caught and not rethrown) then the method's signature shouldn't say it is thrown!
Bad practice with exceptions
There are a couple of things that you should avoid doing:
Don't catch Exception (or Throwable) as a short cut for catching a list of exceptions. If you do that, you are liable catch things that you don't expect (like an unchecked NullPointerException) and then attempt to recover when you shouldn't.
Don't declare a method as throws Exception. That forces the called to deal with (potentially) any checked exception ... which is a nightmare.
Don't squash exceptions. For example
try {
...
} catch (NullPointerException ex) {
// It never happens ... ignoring this
}
If you squash exceptions, you are liable to make the runtime errors that triggered them much harder to diagnose. You are destroying the evidence.
Note: just believing that the exception never happens (per the comment) doesn't necessarily make it a fact.
Edge case: static initializers
There some situations where dealing with checked exceptions is a problem. One particular case is checked exceptions in static initializers. For example:
private static final FileInputStream input = new FileInputStream("foo.txt");
The FileInputStream is declared as throws FileNotFoundException ... which is a checked exception. But since the above is a field declaration, the syntax of the Java language, won't let us put the declaration inside a try ... catch. And there is no appropriate (enclosing) method or constructor ... because this code is run when the class is initialized.
One solution is to use a static block; for example:
private static final FileInputStream input;
static {
FileInputStream temp = null;
try {
temp = new FileInputStream("foo.txt");
} catch (FileNotFoundException ex) {
// log the error rather than squashing it
}
input = temp; // Note that we need a single point of assignment to 'input'
}
(There are better ways to handle the above scenario in practical code, but that's not the point of this example.)
Edge case: static blocks
As noted above, you can catch exceptions in static blocks. But what we didn't mention is that you must catch checked exceptions within the block. There is no enclosing context for a static block where checked exceptions could be caught.
Edge case: lambdas
A lambda expression (typically) should not throw an unchecked exception. This is not a restriction on lambdas per se. Rather it is a consequence of the function interface that is used for the argument where you are supplying the argument. Unless the function declares a checked exception, the lambda cannot throw one. For example:
List<Path> paths = ...
try {
paths.forEach(p -> Files.delete(p));
} catch (IOException ex) {
// log it ...
}
Even though we appear to have caught IOException, the compiler will complain that:
there is an uncaught exception in the lambda, AND
the catch is catching an exception that is never thrown!
In fact, the exception needs to be caught in the lambda itself:
List<Path> paths = ...
paths.forEach(p -> {
try {
Files.delete(p);
} catch (IOException ex) {
// log it ...
}
}
);
(The astute reader will notice that the two versions behave differently in the case that a delete throws an exception ...)
More Information
The Oracle Java Tutorial:
The catch or specify requirement
... also covers checked vs unchecked exceptions.
Catching and handling exceptions
Specifying the exceptions thrown by a method
The following text is from "Effective Java", Item 2:
The traditional Abstract Factory implementation in Java has been the
Class object, with the newInstance method playing the part of the
build method. This usage is fraught with problems. The newInstance
method always attempts to invoke the class’s parameterless
constructor, which may not even exist. You don’t get a compile-time
error if the class has no accessible parameterless constructor.
Instead, the client code must cope with InstantiationException or
IllegalAccessException at runtime, which is ugly and inconvenient.
Also, the newInstance method propagates any exceptions thrown by the
parameterless constructor, even though newInstance lacks the
corresponding throws clauses. In other words, Class.newInstance breaks
compile-time exception checking. The Builder interface, shown above,
corrects these deficiencies.
Please go to this link for full text.
I've been able to follow everything before, "In other words..". Can someone please explain how does newInstance break compile-time exception checking and how does Builder pattern fixes it.
'newInstance' doesn't know ahead of time (at compile time) what exceptions could be thrown, as a normal class method would (because of the way code dependencies are built, and because a class has to make known which exceptions it throws).
The Builder pattern uses a class that takes a request (usually via a method) and creates a new object instance based on steps (most likely defined in that class).
Conceptually a non-abstract factory, and builder are very similar.
public class Main {
private int i;
public Main() throws IOException {
throw new IOException();
}
public static void main(String[] args) {
Class c = Main.class;
try {
c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
In my opinion, if we use class.newInstance() method, we will never know the exactly exception will be thrown by the construction even though the exception is a checked exception and the checked exception isn't shown at the method signature. Just like the example above. If we use class.newInstance(), we will forget to handle the IOException and then get a "broken object". But the Builder pattern won't. Sorry for my pool english and hope you can understand.
Is it possible to throw an exception without catching it?
Example
public void foo() throws SomeException{
// ....
if (somethingCatestrophic) throw new SomeException();
// ....
}
Now I want to call foo, but don't want to catch any errors, as the exceptions should never been thrown at runtime (unless there's a bug)
Unless it is something you are planning for and recovering from locally, it is probably best in this case to use an unchecked exception, e.g., a RuntimeException derivative.
Why don't you catch it inside the method?
Simply use try catch block and go on, if the exception is insignificant and doesn't influence any behaviour of your program.
You can avoid catching an exception, but if there is an exception thrown and you don't catch it your program will cease execution (crash).
There is no way to ignore an exception. If your app doesn't need to do anything in response to a given exception, then you would simply catch it, and then do nothing.
try {
...some code that throws an exception...
} catch (SomeException ex) {
// do nothing
}
NOTE: This is often considered bad style, however, and people may tell you so. The often-cited reason is that, even if you're not going to do anything with the exception, that in most cases you should at least log it somewhere, notify the user, or take some other appropriate action depending on what you app is doing, and what caused the exception in the first place. If you're not sure why an exception is being thrown (maybe it's a bug you haven't solved yet), then generally you should at least log it so you can figure it out later.
If SomeException is a checked exception, the method that calls foo() will either have to catch that exception and deal with it or also be declared to throw SomeException or a parent of it.
If SomeException is a runtime exception, then methods that call it will not need to catch it.
There is a trick, You can play with generics.
/**
* A java syntax glitch to throw any throwable without the need to catch it.
*
* #param throwable to be ignite
* #param <T> the type of the throwable to trick the compiler that it's the one thrown
* #throws T exactly the given throwable
*/
public static <T extends Throwable> void ignite(Throwable throwable) throws T {
Objects.requireNonNull(throwable, "throwable");
throw (T) throwable;
}
This test should pass
#Test(expected = IOException.class)
public void ignite() {
ignite(new IOException());
}
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?
I know the reason why the catching is promoted, but want to do simple and straight tools that enforce their requirements. So if something can went wrong I don't like to catch up but exit the application, crashing with a meaningful exception. Usually this ends up like:
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
which introduces 4 lines of code mess, and introduces the wrapping RuntimeException mess on error output. Sometimes it even motivate people to wrap large try ... catch (Throwable ..) blocks around anything, which is the likely cause for our beloved 'Unknown error occured' alert boxes...
you can use throws keyword with method prototype to avoid try-catch block. which eventually throws the exception to JVM's Default Exception handler which halts the application if no catch block's are specified in your code to handle the exception raised.
Crashing the application at the first sight of an exception is very bad practice. Especially when some work is unsaved and the application is using some resources that needs to be freed and cleaned before the application terminates execution. Some very popular software used to do that... and instead of "fixing" the issue, they introduced a data recoverability features on application restart. However the trick, this is not good software engineering.
At the very least, your application should not crash on the first exception/error encountered, but recover with a meaningful message. It is being lazy to just wrap everything in a RuntimeException (or even Throwable) and, especially, not do anything with it.
Java does not support flags of any kind because there are 1) a workaround, and 2) better ways to handle this situation. For example :
1. Handle the exception in the calling method
You can add the throws keyword in your method declaration, up to your static public void main method, which, if not handling the exception, will eventually crash the application with a stacktrace.
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) throws Throwable {
new Foo().someMethod();
}
}
This method does not offer any means of recoverability and will probably make your user unhappy (with a big meaningless stachtrace if they ran the application from a console, or just nothing at all if they launched it from a shortcut or GUI). Also, if you have some acquired resources, you will not be able to clean them when an exception occurs. At the very least, your main should catch (Throwable e) and output something before throwing the exception above. Something like :
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) {
try {
new Foo().someMethod();
} catch (...) {
// output or log exception here and, optionally, cleanup and exit
}
}
}
** EDIT **
Consider this scenario : a program is initializing some resource for processing some data, then some runtime exception (or error) occurs during processing, the application crash, but the resources are not released or freed. In Java, however, one could do this
public E doSomething() throws RuntimeException {
// declare a bunch of resources
try {
// process resources with unchecked exceptions
} finally {
// free resources
}
// return some result
}
and cleanly exit the method on error or on success, perhaps even logging the runtime error for "posterity".
2. Log the error and return some meaningful value
Logging is a very good practice. You can show your user some message telling them that the operation could not be executed without crashing the whole thing, and giving you some traces of what and where the user were doing. A simplistic logging system could be :
class Foo {
static private final Logger LOG = Logger.getLogger(Foo.class.getName());
public boolean doSomethingImpl(...) {
boolean result = true;
try {
...
} catch (SomeException e) {
LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
result = false;
}
return result;
}
public void doSomething() {
if (!doSomethingImpl(...)) {
// handle failure here
}
}
}
By default, the Logger will output everything to the err output stream, but you can add your own handlers :
// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());
logger.setUseParentHandlers(false); // disable output to err
logger.addHandler(new MyHandler()); // MyHandler extends java.util.logging.Handler
Java already ships with some default logging handlers, one of which writes to file.
etc.
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions?
For a checked exception, you can chose between catching the exception and declaring it in the method header as thrown.
Maybe compiler flags?
No. There are no compiler flags to relax this. It is a fundamental part of the language design. Relaxing the checked exception rules via a compiler switch would cause serious library interoperability problems.
I don't think that there's any way around this for the JVM. Your best bet is to have your methods re-throw the exception, which gets rid of the "mess" in your code, and then have your main program throw Exception. This should propagate the error up to the top of your program.
Keep in mind, however, that the place where the exception actually happens is a much better place to let the user know what happened (i.e., exactly what it was doing when this particular IOException happened). You'll lose this resolution if all errors are simply propagated up to the top level.
You do have the ability to throw your exceptions up a level. Here's an example
public class Foo {
public Foo() {
super();
}
public void disconnect(connection) throws IOException {
connection.close();
}
}
Use "Throws" to avoid the error..but it will not be good programimg practice
Why are some exceptions in Java not caught by catch (Exception ex)? This is code is completely failing out with an unhandled exception. (Java Version 1.4).
public static void main(String[] args) {
try {
//Code ...
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
I get a Exception in thread "main" java.lang.NoSuchMethodError
But this works
public static void main(String[] args) {
int exitCode = app.SUCCESS_EXIT_CODE;
try {
//Code ...
} catch (java.lang.NoSuchMethodError mex){
System.err.println("Caught NoSuchMethodError");
mex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
I get Caught NoSuchMethodError java.lang.NoSuchMethodError:
I thought catching exceptions would catch all exceptions? How can I catch all exceptions in java?
Because some exceptions don't derive from Exception - e.g. Throwable and Error.
Basically the type hierarchy is:
Object
|
Throwable
/ \
Exception Error
Only Throwables and derived classes can be thrown, so if you catch Throwable, that really will catch everything.
Throwable, Exception and any exception deriving from Exception other than those derived from RuntimeException count as checked exceptions - they're the ones that you have to declare you'll throw, or catch if you call something that throws them.
All told, the Java exception hierarchy is a bit of a mess...
Errors aren't Exceptions.
The class Exception and its subclasses
are a form of Throwable that indicates
conditions that a reasonable
application might want to catch.
-- JavaDoc for java.lang.Exception
An Error is a subclass of Throwable
that indicates serious problems that a
reasonable application should not try
to catch.
-- JavaDoc for java.lang.Error
There are certain errors that you may want to catch, such as ThreadDeath. ThreadDeath is classified as an Error, as explained below
The class ThreadDeath is specifically
a subclass of Error rather than
Exception, even though it is a "normal
occurrence", because many applications
catch all occurrences of Exception and
then discard the exception.
-- JavaDoc for ThreadDeath
However, since Thread's stop() method is now deprecated, you should not use it, and thus you should never see ThreadDeath.
Exception is just one kind of Throwable; NoSuchMethodError is not an Exception, but an Error, which is another kind of Throwable.
You can catch Throwable. Error and Exception extend Throwable.
see the Throwable JavaDoc:
The Throwable class is the superclass of all errors and exceptions in the Java language.
As other posters have pointed out, not all throwable objects are subclasses of Exception. However, in most circumstances, it is not a good idea to catch Error or Throwable, because these conditions include some really serious error conditions that cannot easily be recovered from. Your recovery code may just make things worse.
First let's clear up some unfortunate semantic confusion in this discussion. There is the java.lang.Exception class which we can refer to simply as Exception with a capital 'E'. Then you have exception with a lowercase 'e' which is a language feature. You can see the lower case version in the documentation for the Throwable class:
For the purposes of compile-time checking of exceptions, Throwable and
any subclass of Throwable that is not also a subclass of either
RuntimeException or Error are regarded as checked exceptions.
For me it's easier to think about the answer to this question as checked vs. unchecked exceptions (lower case e). Checked exceptions must be considered at compile time, whereas unchecked exceptions are not. Exception (uppercase E) and it's subclasses are checked exceptions, which means you either have to catch any exception that can be thrown by your code, or declare the exceptions that your method could throw (if not caught).
Error and it's subclasses are unchecked exceptions, which means your code neither has to catch an Errors that could be thrown, nor do you have to declare that you throw those Errors. RunTimeException and its subclasses are also unchecked exceptions, despite their location in the class hierarchy.
Consider the following code:
void test() {
int a = 1, b = 0, c = a / b;
}
When run, the above code will produce a java.lang.ArithmeticException. This will compile without any errors, even though an exception is thrown and the code neither catches the ArithmeticException nor declares that it throws this exception. This is the essence of unchecked exceptions.
Consider the location of ArithmeticException in the class hierarchy, especially the fact that this is a subclass of java.lang.Exception. Here you have an exception that derives from java.lang.Exception but because it's also a subclass of java.lang.RuntimeException, it's an unchecked exception so you don't have to catch it.
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.ArithmeticException
If you want to catch anything that could possibly be thrown, catch a Throwable. However this may not be the safest thing to do because some of those Throwables could be fatal runtime conditions that perhaps should not be caught. Or if you do catch Throwable, you may want to re-throw Throwables that you can't deal with. It depends on the context.
As both other posts point out, catch(Exception e) will only work for exceptions that derive from Exception. However, if you look at the tree hierarchy, you'll notice that an Exception if Throwable. Throwable also is the base class for Error as well. So, in the case of NoSuchMethodError, it is an Error and not an Exception. Notice the naming convention *Error vs. *Exception (as in IOException, for example).