Java: How to propagate a "method exit" when tucking-in exceptions? - java

By "method exit" - I mean the actions in a method such as return or throw new... that the compiler considers the end of a method - if you could please tell me the accepted word for "method exit", I will edit the question
My problem is the following:
I do a lot of throw new RuntimeException(...
So, I decided to "tuck it in" as:
public static void quickRaise (String msg) { throw new RuntimeException(msg); }
And then I can reuse it.
(This will help me in the future to enhance the procedure around raising Runtime Exceptions and even
switch to a custom Exception class, without fishing in the code for exception throws)
However, where before I could write:
public MyType doSomething() {
try {
//...
return new MyType (parameter);
} catch (Exception e) {
throw new RuntimeException("msg")
}
}
And the compiler would correctly understand that "this method either exits by return or by throw" and therefore there are no logical "dead ends"
When I changed throw new RuntimeException("msg") to quickRaise("msg"), the compiler no longer considers my method "complete". It complains about a missing return statement, even though quickRaise is semantically equivalent to throw (or at least this is what I am trying to do!)
Let me try to reiterate the problem by a reproductive example (this will not compile, which is the problem):
public static void main(String[] args) {
System.out.println(doSomething());
}
public static String doSomething () {
try {
//... Some fun stuff going on here
return "Something";
} catch (Exception e) {
quickRaise("Could not find handshakes");
//throw new RuntimeException("If you uncomment this line, it will compile!");
}
}
public static void quickRaise (String msg) {
throw new RuntimeException(msg);
}

Your idea is highly inadvisable.
For example, this is just bad codestyle:
try {
someIO();
} catch (IOException e) {
throw new RuntimeException("Problem with IO");
}
The reason it's bad is that you have now obliterated the actual information about the problem. That information is locked into 5 separate parts of that exception you just caught: Its type (for example, FileNotFoundException, its message (e.g. "Directory /foo/bar does not exist"), its stack trace, its causal chain, and as throwables are objects, any particular extra detail for that particular kind of exception (such as the DB-engine-specific error coding for some SQLException).
Throwing this info away is silly.
All you'd need to do to fix this, is to add the cause:
} catch (IOException e) {
throw new RuntimeException("IO problem", e);
}
Now the IOException is marked as the cause of the exception you are throwing, which means in error logs you'll see it + the message + the stack trace of it + the stack trace of any causes it had as well.
All you need to do to make the compiler realize that the method ends here, is to throw it:
public static RuntimeException quickRaise(String msg) {
throw new RuntimeException(msg);
return null; // doesn't matter, we never get here
}
// to use:
throw quickRaise(msg);
But, as I explained before, this is a very bad idea.
Secondarily, having the idea of 'I just want to throw an exception and maybe later I want to replace the kind of exception I throw' also doesn't really work out: You need to pick a proper exception for the situation, therefore you cannot write a one-size-fits-all throw method in the first place.
Okay, so what do I do?
Primarily, learn to embrace throws clauses. If your method fundamentally does I/O (for example, the javadoc of it and/or the name makes that obvious, it is for example saveGame(Path p), or scanUserHome), then it should be declared to throws IOException.
If your method is an entrypoint (as in, it is the first point where your own code begins running), then your method should be declared to throws Exception. For example, your public static void main() method should throws Exception. Sometimes an entrypoint isn't main but something else (a webhandler routing hook for example), and sometimes backwards silly franeworks prevent you from doing that, but there tends to be a wrap functionality (such as } catch (Exception e) { throw new ServletException(e); }).
For exceptions which are both [A] fundamentally not part of the method's purpose, but more part of an implementation detail and [B] is very unlikely to go wrong and there's not much you can do other than hard crash if it would, then, yeah, rewrap as RuntimeException. There isn't a lot of point in ever changing this 'globally' for all such exceptions. At best you belatedly realize that failure is a bit more likely than you originally thought and either create a proper exception for it and document this behaviour. But that's, again, on a per-method basis, not something you can apply in blanket fashion.

Your approach is fundamentally at odds with the need for the compiler to see that the flow terminates at the throw statement.
I'd suggest having a utility method that just constructs an exception, which you then throw from the original point.
It's either than or put dummy returns after each call to quickRaise().

Related

Throwing an exception after retrying a block of code

Is it correct, safe and sane to throw an exception after a successful retry? Which programming principle is violated in this example?
class B {
private int total;
public void add(int amount) throws Exception {
if (amount < 0) {
throw new Exception("Amount is negative");
}
total += amount;
}
}
class A {
public B b = new B();
public void addToB(int amount) throws Exception {
try {
b.add(amount);
} catch (Exception ex) {
try {
b.add(-amount);
} catch (Exception ex2) {
}
throw new Exception("Amount was negative. It was inverted and then added.");
}
}
}
your code is working but since you are calling a addToB() method which throws exception inside a catch block you must implement another try-catch block within try-catch block. and at the end you are throwing a exception even after having so many try-catch blocks which is not good since the exceptions if not handled can cause problems and its very bad practise to throw exception if the method was success. i see that you need the user to know what happened inside the method, you can return a string from the
method which will tell the user what happened inside the method.
ex: -
public String addToB(int amount){
String msg = "";
try{
b.add(amount);
msg ="successful";
}catch(Exception ex){
try{
b.add(-amount);
}catch(Exception ex2){
}
msg= "Amount was negative. It was inverted and then added.";
}
return msg;
}
even this is not the best practise bt you might need check this.
There are a few sound principles that you are violating.
Throwing java.lang.Exception is bad in such situations (or in general), even if you are writing toy code. You should consider using a RuntimeException. The idea is pretty simple. You know nothing about the amt until you run the program. If a user or client of this code provides negative argument, then it an unexpected argument only to be known at runtime. Do not promote the Pokemon exception handling anti-pattern.
You are utilizing the baklava code pattern. This should be avoided.
The more serious error you are committing is doing the thing anyway exceptionally or not. Here's a use of your classes:
public static void main(String[] args) {
A a = null;
try {
a = new A();
a.addToB(10); // no exception here, total should be 10
a.addToB(-10);
} catch (Exception e) {
// exception here, but the total should be 20, or not?
System.out.println(a.getTotalFromB());
}
}
Now, in this case, the value of total is 20 even when an exception was thrown! Almost always, exceptions should be used to signal exceptional conditions where the expected things do not happen. This, to me, is a serious violation.
It's possible to do this, but this is a bad idea for three reasons:
You're using exceptions as control flow. This is an antipattern which is to be avoided.
You're throwing Exception. If this is truly exceptional behavior, then you should look to create your own [checked] exception type.
You're catching Exception in that block. If b is null then you're not guaranteed that the input was invalid at all.
Let's start with the flow.
In this scenario, it doesn't make immediate sense why a negative value is considered exceptional enough to recover from, which is what the checked exception implies.
Effectively, if the first attempt seems to fail with a negative number, the idea is to try it again by negating the negative, resulting in a positive number.
Something like this can be mitigated in several ways, depending on what the negative value means to the business:
Throwing multiple exceptions (least preferred)
Silently drop it, but log the value passed in (less preferred)
Throw an unchecked exception and do not require its callers to catch it (preferred)
With my preference, the code above would look like this:
public void add(int amount) {
if(amount < 0)
throw new IllegalArgumentException("Amount may not be negative");
total += amount;
}
This would put the onus of ensuring that the input is correct and appropriate for this method on the developer as opposed to the application. Unit tests here would go a long way to ensure the behavior that you want.
Now, to throwing Exception: Exception is checked meaning that everyone has to catch it or declare it to be thrown, which is unpleasant to code.
Checked exceptions should be reserved for something that the user can do to recover from (for instance, FileNotFoundException - user should be sure that the file path is correct).
Lastly - you should not be catching Exception. That's too broad of an exception to catch, considering that b may be null.

Custom Unchecked Exceptions

Okay guys I've been trying to figure this out for the past day or so. My homework assignment has me creating both Unchecked and Checked Exceptions. The checked exceptions I believe I get basically they must be handled before compiling (With try & catch or throwing it to the next thing that calls it. For unchecked exceptions I don't understand how custom ones work. They are caught at runtime and don't necessarily need to be thrown or encased with try & catch but if they're custom how does the IDE or whatever know what to look for? Example: One of my custom Unchecked files is supposed to trigger if the user adds a pokemon but the party is full, but how do I tell the IDE that that's what needs to happen? My Exception file looks like:
public class PartyIsFullException extends RuntimeException {
public PartyIsFullException() {
super();
}
public PartyIsFullException(String message) {
super(message);
}
}
and then I want to implement it in this method, but idk how to do it. I realize now I can't throw them because the user won't be expecting them and therefore won't try to catch them.
public void addToParty(String name) throws PartyIsFullException {
boolean exists = false;
for (int i = 0; i < 152; i++) {
exists = (name.equals(pokedex[i]));
}
if (exists) {
throw new PokemonAlreadyExistsException();
} else {
if (partyPos < 6) {
party[partyPos] = name;
partyPos++;
} else {
throw new PartyIsFullException();
}
}
}
I realize now I can't throw them because the user won't be expecting them and therefore won't try to catch them.
You can throw them!
In a real project, it should be clearly documented.
/*
* #throws PartyIsFullException if isPartyFull() would return true
*/
public void addToParty(String name) throws PartyIsFullException {...}
Usually an unchecked exception is used for a situation where the client of the method is avoiding the exceptional condition themselves e.g.:
if(theParty.isPartyFull()) {
// tell the user the party is full
// and they can't add more Pokemon
} else {
theParty.addToParty(thePokemon);
}
And thus they shouldn't have to explicitly catch it because they are already handling that circumstance.
If the exception is thrown and there is not a try-catch outside, it will throw all the way up to terminate the thread. (For a small program with just main, this means the program crashes.)
Although you don't know if a certain custom unchecked exception could or not be thrown from a certain method you still can catch it (or it's superclass Exception). Having custom exception against provided by Java could add some useful details specific for your exceptional case (i.e. exception name should be meaningful so that it makes it easier to read your logs).
Custom (unchecked) exception creation and it's content could also be tuned to suit your particular need. E.g. PartyIsFullException constructor could take a Party object and format it's state into a String.
In case you don't need to facilitate your unchecked exception creation/presentation it's OK to go with RuntimeException assuming you provide a descriptive message.

what is the effect that explicits the "throw exception" in the method signature

--the effects of case 1 and 2 are the same, why need to add the exception declaration in method signature?
//case 1
public void doSomething() throws Exception {
//do Something
}
public void Caller() {
try {
doSomething();
} catch (Exception e) {
//handle the exception
}
}
//case 2
public void doSomething() {
//do Something
}
public void Caller() {
try {
doSomething();
} catch (Exception e) {
//handle the exception
}
}
reference:
what is the use of throws Exception
The throws declaration is used to declare which checked exceptions your method throws.
For instance, if I write this code:
public void doSomething() throws SQLException {
}
any code that calls this method must have a try/catch block for SQLException, Exception, or Throwable... or it can have its own throws declaration for one of those 3.
In this case, there is no difference, except that you're alerting the compiler to an exception that you're not going to be throwing.
It's also a bad idea to catch throw "Exception" - in both cases, you want to deal a particular exception that has a particular meaning. When you're catching, the only reason to use a try block is if you expect a particular exception, so you should catch that one. This way, if some unexpected exception comes up, you don't try to handle it the wrong way. (instead, your program fails, and you know there's a condition you have to deal with) When you're throwing, you want to throw a particular exception, either one you make up, or a standard one that has a known meaning, so the calling function knows what to deal with. For example, if your doSomething might throw an ArrayIndexNotFoundException if the widgets are not frobnicated, you might want to catch the ArrayIndexNotFoundException and throw a WidgetNotFrobnicatedException. Any time you throw an exception, your javadoc should specify exactly what circumstances will trigger that issue, so the user of your code has a chance to address this possible failure.
(there is one circumstance when I can see catching Exception, and that's if you want to fade to some graceful halt if things go wrong unexpectedly - in that case, in your catch block you'd log the issue, possibly alert a developer, and throw up some sort of "Sorry, error number 3542 has occurred, please restart the program" message.)
If your doSomething method, has the chance to throw an exception and you don't want to catch it, you should add this throws Exception on the method.
Unless it's an exception that you want to handle immediately in that method, it's good practice to use throws [specific Exception] so that the exception can be handled further up in the code.
It's somewhat commonplace to have a generic Throwable catch at the top that "gracefully crashes" in case something goes wrong.

Java Exception handling when arguments are hard-coded

I have a design level doubt regarding creating APIs in Java. Suppose I have a class as follows :-
class Test
{
public final static String DEFAULT_ENCODING = "utf-8";
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
// do something
}
}
}
I know that the UnsupportedEncodingException would never arise as I'm using a static string as the input to toBytes. It doesn't make sense to have encodeIt do a throws UnsupportedEncodingException because I dont wish the API users to expect and catch that error either.
In such cases, is the best practice to have an empty catch block?
It is a bad idea to have empty catch blocks. Even though your reasoning seems correct this design will at some stage cause you endless debugging and searching once exceptions do start happening and your code is swallowing them. I would wrap your exception in a RuntimeException here and throw that. Like so:
public encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
catch(UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
This way your exception will not stay hidden might it occur nor do your API users have to cater for it.
I do something like this:
public byte[] encodeIt(String input) {
try {
return input.getBytes(DEFAULT_ENCODING);
}
catch (UnsupportedEncodingException e) {
throw new ShouldNeverHappenException(e);
// or: throw new IllegalStateException(e);
}
}
(where ShouldNeverHappenException is a runtime exception, of course).
This way, if someone happens to change the constant value, or add an encoding argument, the method will fail fast and the problem will not go unnoticed or buried in log files.
In such cases, is the best practice to have an empty catch block?
I don't feel that's a good idea, ever. Empty catch blocks mean that something could happen and you'll never know.
Don't throw this exception. Catch it and log it so you can check your assumption that it can never happen, but at least you'll know if never arrives.
I usually follow the strategies outlined by other answers to this question (like soften the checked exception to RuntimeException). However, one interesting alternative is to use an assertion:
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
assert false;
return null;
}
}
When assertions are enabled with the -ea JVM flag, this method would throw an AssertionError if ever UnsupportedEncodingException were thrown. An annoyance is the need to return a value (such as null), otherwise the code won't compile.
So perhaps the following is "nicer":
public byte[] encodeIt(String input)
{
try {
return input.getBytes(DEFAULT_ENCODING);
} catch(UnsupportedEncodingException e) {
throw new AssertionError("Unexpected.", e);
}
}
Not so materially different than throwing RuntimeException except that AssertionError is nicely self-documenting. And, being a subclass of Error, it represents a more fundamental failure than Exception normally implies. No chance for a catch (Exception e) clause somewhere higher up on the stack handling this thing (were it to ever occur).
The best way I think is to avoid checked exception. Just use an unchecked one. Then you will take the best of 2 worlds: you do will signal the error if it really happens and you won't force the user of your API to handle the exception.
If you are very, very sure that it would never happen, leave an empty catch block.
But for practice, just in case you change the code later on, it is better to log it to the console when the exception happens.

does throws exception leads the program to a pre written code

( patience requested as i'm new to programming )
when you add the phrase throws ABCexception in method declaration like this
public static void main(String[] args) throws ABCException {
}
does it mean that the you expect the method could generate an ABC exception and by writing throws ABCException ... when this exception occurs .. this exception will be caught and some prewritten code in java language will be executed corresponding to the ABCException. ?
thanks
throws declares that the method may throw the exception so the code that invoke this method must be prepare for it.
Being prepared for exception means that the code may catch the exception or re-throw it up.
Consider the constructor new FileInputStream(File pFile) which will create a FileInputStream from a File object. Since the file may not exist or not readable the constructor will throw FileNotFoundException (as declared).
So any code that call this constructor will either catch or rethrow it.
Catching it, the code will taking care of that exception by themself while rethrowing it, the code will let its caller take care of it.
Consider the following two codes:
Code 1: Catch -> Take care of it
public String readTextFile(File pFile) {
try {
FileInputStream FIO = new FileInputStream(pFile);
... // Do the reading and return
} catch (FileNotFoundException E) {
System.err.println("The file is not found");
}
}
Code 2: Throw -> Let the caller take care of ot
public String readTextFile(File pFile) throws FileNotFoundException {
FileInputStream FIO = new FileInputStream(pFile);
... // Do the reading and return
}
So the caller of readTextFile will have to catch or rethrow it too.
This mechanism ensures that someone have to take care of the exception in someway.
I hope I help.
The thows ABCException statement, before the function definition starts in earnest is just to indicate that this function may throw such an exception.
The actual throwing of the exception would happen within the code of the function. With code like the following (note the lack of an 's' at the end of "throw")
throw new ABCException();
The exceptions are then passed on "up" through the chain of the program logic that called this function this function, until one these "catches" the exception and deals with it. In case the exception "bubbles back" all the to the main() function, and if said exception isn't caught there either, a default handler deals with it, typically by printing out the exception to stderr/stdout and halting.
The way this exception could be caught would be with a try-catch construct, as in:
try
{
// do some stuff if needed
xy = fct(); // this fct may throw the ABCExeption...
// do more stuff as well
}
catch (ABCException e)
{
// for debugging you can do this
e.printStackTrace();
// otherwise you could deal with this exception as desired.
}
In re-reading the question, I noted that the function which is declared with throws ABCException and that is a bit odd, because main is the first method in the chain of function calls, meaning that there is nothing before main() which could catch an exception (other than the default exception handler of the Java Runtime, which wouldn't do anything specific for ABCException; it would just "dump it" to the console (or elsewhere for GUI-based apps) like any other exception.

Categories

Resources