try/catch/finally statements have become a modern programming standard.
For example you could be trying to connect to a database, if the connection fails you could throw an error. Basically throwing an error means “An error has occured that my code function either can’t deal with, or doesn’t want to deal with, if you’d like to deal with it, catch it”
With errors you can either catch all errors a function or code block may throw, or just specific erros that you’re expecting. If an error your try block doesn’t catch, it may get caught by a try/catch block further up the code chain – if it never gets caught you get a program error.
In many programming languages, if you try to perform an “illegal action” the program will crash because you’ve attempted the impossible (like dividing by zero) or the disallowed (like accessing memory you’re not supposed to).
The **try** block basically says “check this code for illegal actions, and if there are any, go to the **catch** block. If there aren’t any, do the code.”
Sometimes it depends on your definition of “crashing”
Consider a simple function that divides two numbers. Given A and B, it returns A/B. Obviously, this is undefined for B=0. If you ignore this, the program will “crash hard” when given B=0. the error will originate from some part of the architecture below the program you’re writing, and you will have limited control over how it is handled. Depending on the environment, it might send no information to the user about what happened, or that information could be unhelpful for diagnosing the problem.
However, you can put in code to catch the problem by testing for B=0 before doing the calculation. If it finds that B=0, it could return a helpful error message to the user telling them to try a different value for B. Depending on the application, you could also choose some fallback behavior like setting B to a very small nonzero number.
It doesn’t stop it from crashing necessarily, but it can allow a program to deal with errors that come up.
Consider code that outputs 100 divided by user input. You could just “ask user for input, divide 100 by the user input, display the result”. But what if the user entered “0”? Or what if the user entered “TryingToBreakThisProgram”? In those cases, the code would be attempting to calculate “100/0” or “100/TryingToBreakThisProgram”, neither of which can be done. That makes the program crash. But a programmer could wrap the code in a “try” block, followed by a “catch” block. Once you’re in the catch block, there’s a variable that will tell you what caused the crash. So maybe in your catch block you have “if the error is a divide by zero error, tell the user that the number needs to be not zero”, or “if the error is that the value isn’t a number, tell the user that they need to enter a number”. And if it’s something else that you hadn’t anticipated, maybe you give up and let the program crash (that’s done by kind of “rethrowing” the error).
When an exception is thrown, it “bubbles up” until it’s “caught” and handled by something. If nothing catches it, the execution environment will handle it, which it usually does by closing the program. If you catch it yourself you can have the program gracefully recover from the error, or at least log the error appropriately before you close the program yourself.
There are different ways code might not work. The one we’re talking about here is when you break a rule the code has somewhere. Like this function only works with numbers and that one only works with words. If you break the rules, the code tells you it can’t do that by ‘throwing an exception.’ It knows to do that because the person who wrote that bit of code told it to.
You can tell the computer “hey, if this breaks any rules, do this other thing instead.”
If code would cause the whole computer to crash, try/catch might not help.
your program is “bring a forkful of food to my mouth” .. the exception is “food falls off fork in transit”. the food will land somewhere… but will it hit your plate? your napkin? your lap? your nice shirt? the floor?… the level of mess depends on what “catches” the food (exception). a try/catch puts a plate under your fork so the level of “mess” is minimal and you can keep eating.. not catching that exception means that your lap (or floor) catches it and you have to stop your program (eating) to clean up the mess…
Let’s make a metaphor for how programs work.
Imagine a person at a desk. They have an “in” box, and an “out” box.
Some other workers put folders in the “in” box. Their job is to take the folder out and open it up. The folder contains pieces of paper with math problems on them. The person solves each math problem, and when they solve all of them, they close the folder and put it in the “out” box.
Now imagine some papers have weird things like, “Use the answer to problem 3 on the last page for this value.” This is a little more complicated but we can imagine the person handling it.
Some folders have other folders inside. So when that happens they do the math on all the papers before the “inner” folder, then open the “inner” folder. They treat it like the “outer” folder: they do the math on the papers inside, then close the folder. Then they do the math on the rest of the papers in the “inner” folder.
Now imagine a folder with folders that have folders with folders in them. That’s a good way to describe a complicated program. But we can follow the simple steps above to imagine the person slowly working through all of the math papers in sequence and understand how the person works through it.
Now let’s add exception handling.
The “try/catch” part of the program structure is like if the page before a folder has a special instruction:
> If any of the problems in the upcoming folder cannot be solved, please do these steps…
The “throw” part of the program structure is like a math problem has these special instructions:
> If box 3 on the last page is zero, this problem is unsolvable.
So what happens when the person gets to that instruction is they stop and say, “Oh.” They cannot continue because they cannot solve any more problems. So they close this “inner” folder.
Then they move backwards and look at the piece of paper from before the folderr. They see, “If any of the problems in the upcoming folder…” and say, “Ah, here we go.” Now they do the steps. When they finish, that’s it for this stack of papers. They close the folder they are in, move it out of the way, then proceed with the next papers.
This can go very far back. They might be 10 folder layers deep. They will still dutifully work backwards, inspecting papers and closing folders until they find, “If anything ahead cannot be solved…”. If they cannot find instructions like that before they close the final “outer” folder, then that set of problems is unsolvable. They stamp it “TERMINATED” and put it in their “out” box.
—
Inside the code that compilers generate, they do things like this. When code enters a try/catch, a little bit of information about that gets stored in memory. As code calls different parts of itself, it leaves little bits of data in memory about how it got to where it is.
When something throws an exception, it changes how the program works. It stops moving forwards and starts moving backwards. It follows the trail of breadcrumbs describing how it got to where it is, and at each marker it asks, “Is there a catch block I can go to here?” If not, it keeps working backwards. If it reaches the end of the trail before it finds a catch block, the program ends.
Using try and catch you can tell the program what to do in case of an error and not just die horribly; ie usually recover gracefully. You can have something like try { open a file } catch { (if file not found) tell user it’s not found and return “no file found sorry” } otherwise it would be that if file not found -> crash and exit process
Latest Answers