Was hoping for an explanation as to what it means to pass an exception up the calling chain by declaring the exception in my methods throws clause and why I would want to do that.
Here is an example of my understanding of throwing own exception.
public class ExceptionThrow {
char[] charArray = new char[] { 'c', 'e', 'a', 'd' };
void checkArray() throws ABException {
for (int i = 0; i < charArray.length; i++) {
switch (charArray[i]) {
case 'a':
throw new ABException();
case 'b':
throw new ABException();// creating the instance of the
// exception anticipated
default:
System.out.println(charArray[i] + " is not A or a B");
}
}
}
public static void main(String[] args) {
ExceptionThrow et = new ExceptionThrow();
try {
et.checkArray();
} catch (ABException ab) {
System.out.println(ab.getMessage() + " An exception did actually occur");
} finally {
System.out.println("This block will always execute");
}
}
}
class ABException extends Exception {
}
How would I pass the exception 'up the calling chain'?
regards
Arian
The "calling chain", also commonly known as "stack trace", is the list of all nested method calls leading to a single line of execution. In your case, its depth is 2 : main calls checkArray, but there can be dozens of methods.
When an exception occurs in the code, it interrupts the current method and gives the control back to the previous method on the stack trace. If this method can handle the exception (with a catch), the catch will be executed, the exception will stop bubbling up. If not, the exception will bubble up the stack trace. Ultimately, if it arrives in the main and the main cannot handle it, the program will stop with an error.
In your specific case, the throw new ABException() creates and throws an ABException that interrupts the checkArray method. The exception is then caught in your main with catch(ABException ab). So according to your question, you can say that this code passes the exception 'up the calling chain'.
There are many more things to say, notably related to checked/unchecked exceptions. If you have some more specific questions, feel free to ask.
First, you'll have to add throws ABException to the main method and then either delete the block that catches the exception or rethrow it after logging
throw ab;
You can do it for example by not catching it in main(), but passing it to the piece of logic that called main(). In this case, it's trivial, as main() is your program's entry point...
You could also rewrite your method
void checkArray() throws ABException {
for (int i = 0; i < charArray.length; i++) {
check(charArray[i]);
}
}
void check(char c) throws ABException {
switch (c) {
case 'a':
throw new ABException();
case 'b':
throw new ABException();// creating the instance of the
// exception anticipated
default:
System.out.println(c + " is not A or a B");
}
}
Now it becomes more clear how checkArray() "passes the exception from check() up the calling chain"
Related
Here is a super simple java code
public class Main {
public static void throwExample() {
throw new Exception(); // IntelliJ says that something's wrong here.
}
public static void main(String[] args) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream("aa.txt");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i = 0; i < 10 ; i++) {
baos.write((byte) i);
}
System.out.println(Arrays.toString(baos.toByteArray()));
}
}
On the third line I commented, IntelliJ says that there's something wrong here. So I randomly changed the code and, when I did the things like below,
public static void throwExample() // throws Exception
it became ok.
But I saw lots of examples using
'throw' keyword without 'throws' together, such as
class Exception2{
static int sum(int num1, int num2){
if (num1 == 0)
throw new ArithmeticException("First parameter is not valid");
else
System.out.println("Both parameters are correct!!");
return num1+num2;
}
public static void main(String args[]){
int res=sum(0,12);
System.out.println(res);
System.out.println("Continue Next statements");
}
}
What would the problem in my code?
But I saw lots of examples using 'throw' keyword without 'throws'
together
In java, there are two main categories of exceptions which are
Checked exceptions
Unchecked exceptions
If you throw a checked exception, you need to catch it by either surrounding the piece of code that could throw the checked exception with try catch block or by adding throws keyword in method signature.
On the other hand, if your code throws unchecked exception, it is not necessary to catch it. Hence java compiler doesn't complains about you not adding a throws keyword in method signature in your second code example.
Exception is a CheckedException it needs a throws. All exceptions are inherit from RuntimeException are UncheckedException and dont need a try/catch or throws.
More: Java: checked vs unchecked exception explanation
I currently did my programming assignment which was said to use recursion to find the factorial of a number that the user inputs. I successfully did it and it worked, but I decided to expand the code a bit and add an exceptions for kicks.
Basically I want the program to prompt the user to enter a number greater than or equal to 0 and if the user enters a number that is less than 0 I want an exception to be thrown, caught and handled. I know in this code I'm using the incorrect exception which is StringTooLong, but I don't know any other exceptions off the top of my head. By the way when I run my code I get an error of cannot find symbol at the throw lengthException.
Here's my code:
import java.util.Scanner;
public class Recursion {
public static void main(String args[]) {
long userNum;
System.out.println("Enter a number to check it's factorial");
Scanner scnr = new Scanner(System.in);
userNum = scnr.nextLong();
StringTooLongException lengthException =
new StringTooLongException ("String has too many characters");
System.out.println(fact(userNum));
}
public static long fact(long userNum) {
try {
if(userNum < 0) {
throw lengthException;
} else if(userNum == 1 || userNum == 0) {
return 1;
} else {
return userNum*fact(userNum-1);
}
} catch(Exception e) {
System.out.println("Enter a number that is greater or equal to 0," + e);
}
}
}
Try:
throw new StringTooLongException();
And you can remove the following:
StringTooLongException lengthException =
new StringTooLongException ("String has too many characters");
Though as #KevinO and the others have suggested, it is more suitable to be using IllegalArgumentException, e.g.
throw new IllegalArgumentException();
Or, you could create your own custom Exception, e.g.
public class InvalidInputException extends Exception {
public InvalidInputException(String message) {
super(message);
}
}
You have declared lengthException in main, and tried to use it in fact. It is hence out of scope for the method fact(long userNum). Thus the error you got.
You can take a look at this for more on exceptions.
You could use NumberFormatException:
...
if(userNum <= 0)
{
throw new NumberFormatException("Must be a positive integer");
}
...
} catch (NumberFormatException e) {
System.err.println("Enter a number that is greater or equal to 0," + e);
}
You need to use new to fix your throw lengthException error. Also I think you meant to use 'throw new StringTooLongException();'
You should also learn more about what an exception is and what it is used for. One thing is that an Exception is actually a class, and any subclass of the Exception class is itself an Exception. So, if you wanted, you could create your own exception by simply extending the Exception class. This is why you must use the new keyword when throwing the exception: you are throwing a new instance of an Exception (or one of its subclasses).
You can see a list of some top-level exceptions by exploring the direct known subclasses section in the JavaDoc for the Exception class.
A clean alternative for your implementation is to create your own custom Exception which fits your requirements.
For example, you can create a custom exception class as follows:
public class InvalidInputException() extends Exception
{
public InvalidInputException()
{
super();
}
public InvalidInputException(String message)
{
super(message);
}
}
This implementation would allow you to throw new InvalidInputException() in your try-catch block, and is more informative to the user.
I am wondering if this is possible to do without writing a try/catch block for every single call. I want to be able to tell which method threw the exception so I can handle them differently. Consider the following two (fairly identical) methods:
public void setBranchID(String ID) throws NumberFormatException{
if(ID.trim().length() != 0 && ID != null){
try{
branchID = Integer.parseInt(ID);
}catch(NumberFormatException ex){
OutputFunc.printError(ex); //Prints the stack trace to console
throw ex;
}
}
else{
branchID = null;
}
}
public void setCashOnHand(String cash) throws NumberFormatException{
if(cash.trim().length() != 0 && cash != null){
try{
cashOnHand = Double.parseDouble(cash);
}catch(NumberFormatException ex){
OutputFunc.printError(ex);
throw ex;
}
}
else{
cashOnHand = null;
}
}
What I want to do:
try{
setBranchID(String1);
setCashOnHand(String2);
//Other methods
}catch(NumberFormatException ex){
if(/*Exception came from setBranchID*/){
//Code
}
else if(/*Exception came from setCashOnHand*/){
//Code
}
}
You'll need to create a custom exception, which would have some sort of enumeration which would provide hints as to where the error took place:
public enum ErrorType {
BranchId,
CashOnHands
}
public class MyException extends Exception {
private ErrorType errorType;
public MyMyException(string message, ErrorType errorType) : super(message) {
this.errorType = errorType;
}
public ErrorType getErrorType() {
return this.errorType;
}
}
Then you create an exception like so: throw new MyException(..., ErrorType.Branch) and then, in your handling statement:
...
catch(MyException e) {
switch(e.getErrorType) {
case ErrorType.BranchId:...
}
}
you do not necessarily need to create a new exception (even though its probably nicer) but you can just change the message returns from the exception :
public void setBranchID(String ID) throws NumberFormatException{
if(ID.trim().length() != 0 && ID != null){
try{
branchID = Integer.parseInt(ID);
}catch(NumberFormatException ex){
OutputFunc.printError(ex); //Prints the stack trace to console
throw new NumberFormatException("setBranchID error : " + ex );
}
}
else{
branchID = null;
}
}
Then you can get the exception message if it starts with the setBranchId:
try{
t.setBranchID("xxx");
t.setCashOnHand("xxx");
//Other methods
} catch (NumberFormatException ex){
if (ex.getMessage().startsWith("setBranchID")) {
System.out.println("error from setBranchID method");
}
.....
}
You can also try something like this---
try {
setBranchID(String1);
setCashOnHand(String2);
} catch (Exception e) {
StackTraceElement se[] = e.getStackTrace();
String s = se[0].toString();
int startIndex = s.indexOf(".");
int endIndex = s.indexOf("(");
String newstr = s.substring(startIndex + 1, endIndex);
}
newstr will have the name of the function that throws the exception. You can compare it and do your desired processing.
I tried it and its working fine.
I hope it would help you.
You can avoid to write a try - catch block for every single method simply obtaining the method name directly from the stack trace like this:
public class TestClass {
public void testMethod1(){
int x = 1/0;
}
public void testMethod2(){
int x = 1/0;
}
public static void main(String[] args) {
TestClass c = new TestClass();
try {
c.testMethod2();
} catch (Exception e){
System.out.println(e.getStackTrace()[0].getMethodName());
}
}
}
The main method above prints testMethod2
The answer to your question is quite simple, don’t re-throw and exception. But maybe you want to do this, so then probably your custom exception is the easiest way because you can enforce that it has the information about the original method. But can I just make some remarks, don’t read if not interested but please consider.
This code you have written looks very similar to the code I wrote when I first started doing GUI programming, I thought using this functionality from checked exceptions is a good idea for validating user input but it’s not. I even stuck checked exceptions in the data objects themselves, for instance in the setters of an employee class.
Eventually what you’ll find that methods, which have nothing to do with exceptions generated by methods nested deep in your control structure are having to handle exceptions or throw an exception which has nothing to do with them, soon every method in your code will be doing this, for many different exceptions.
What is the answer then? You’ll find that preventing exceptions will be your best attack. Use components which enforce the correct data, such as formatted text fields. Then in your code you can know with certainty that methods are not going to have exceptions. If you have complex validation going on, then just think about how you can design your code, look at some GUI patterns such as the MVC pattern (there are at least 2 versions of this pattern by the way). Then there are alternatives, I found returning an enumeration value then using a switch statement for each case can be a nice solution too. Or another idea is that each error message you can merely append to a string and then output as well, anything but throwing exceptions, and if you are going to throw an exception, don’t throw a checked one unless someone is going to die if you don’t.
I think it’s a fine art to know when it is a good idea to throw an exception, but shouldn’t be your first choice.
I have a method which adds two vectors together and I need to return an exception if the length of these vectors are not the same to start off with.
I have written a code
public static Vector vectorAdd(Vector v1, Vector v2) throws IllegalOperandException{
if(v1.getLength() == v2.getLength()) {
double[] temp = new double[v1.getLength()];
for(int i = 0; i < temp.length; i++) {
temp[i] = v1.get(i) + v2.get(i);
}
Vector v3 = new Vector(temp);
return v3;
} else {
throw new IllegalOperandException("Length of Vectors Differ");
}
}
But once I compile my main method
else if (userInput == 2) {
System.out.println("Please enter a vector!");
System.out.println("Separate vector components by "
+ "using a space.");
Vector v1 = input.readVector();
System.out.println();
System.out.println("Please enter a vector!");
System.out.println("Separate vector components by "
+ "using a space.");
Vector v2 = input.readVector();
System.out.println();
System.out.println();
System.out.println(LinearAlgebra.VectorAdd(v1, v2));
There is an error of
error: unreported exception IllegalOperandException; must be caught or declared to be thrown
System.out.println(LinearAlgebra.vectorAdd(v1, v2));
I have been googling for an hour now, but I do not get what is the problem.
I'm pretty sure it's something related with try and catch, but I have no idea how to fix it.
What should I do?
Whenever you do something that can throw a particular type of Exception, you have to have something in place to deal with it. This can be either of two things:
surround it with a try/catch block;
add the Exception type to the throws clause of your method.
In your case, you're invoking the LinearAlgebra.vectorAdd() method, and that method can throw an IllegalOperandException (presumably if one of its arguments is dodgy). That means that the method in which you invoke it can also throw that exception. Either catch it, or add throws IllegalOperandException to the signature of the method in which that line occurs. Sounds as though it's your main method, so it would become
public static void main(String[] args) throws IllegalOperandException {
//...
}
This is called letting the exception propagate upwards.
To catch the exception instead, you'd have
try {
System.out.println(LinearAlgebra.VectorAdd(v1, v2));
} catch (IllegalOperandException e) {
// do something with the exception, for instance:
e.printStackTrace();
// maybe do something to log it to a file, or whatever...
// or you might be able to recover gracefully...
// or if there's just nothing you can do about it, then you might:
System.exit(1);
}
That will allow you to deal with it when it happens. It enables you to return some specific result instead if it all goes wrong, or (in this case) print an error and terminate the program.
Here I have used throws in method signature when i am going to call this method from some where else that is not asking me to handle the exception.
public class Exception {
int a, b, c;
void set(String data[]) throws NumberFormatException, ArrayIndexOutOfBoundsException {
a = Integer.parseInt(data[0]);//convert the string into int. eg1.("12" ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
}
void divide() throws ArithmeticException {
c = a / b;
}
void disp() {
System.out.println(a + " / " + b + " = " + c);
}
}
when i am going to call this method from some where else that is not asking me to handle the exception.
Yes, because both are RuntimeExceptions and must not be caught.
Read the java tutorial about exceptions and unchecked exceptions.
Sometimes you see methods that declare RuntimeExceptions, like your method does. It is a way to document the exceptions that might be thrown even if you don't catch them.
In addition to user3168013's comment
how can we able to convert unchecked exception to checked exception .
Every exception can have a cause. A cause is another exception that lead to it. If it has no cause it is a root exception. So you can just create an instance of a checked exception, pass it the unchecked exception as it's cause and throw the checked expection.
For example define your checked exception
public class DataFormatException extends Exception {
public DataFormatException(Throwable cause) {
super(cause);
}
}
and then throw your own
void set(String data[]) throws DataFormatException {
try {
a = Integer.parseInt(data[0]);// convert the string into int.
// eg1.("12"
// ---> 12) eg2.("df23" ---> fail)
b = Integer.parseInt(data[1]);
c = 0;
} catch (NumberFormatException e) {
throw new DataFormatException(e);
} catch (ArrayIndexOutOfBoundsException e) {
throw new DataFormatException(e);
}
}
Of course it would be better to give a detailed exception message depending on the cause, but this is just a short example.
Both Exceptions are unchecked Exception. Unchecked Exception are handled at runtime.
Its developer choice how to handle or not runtime Exception , compiler never force you handle.
Find more on handling Runtime Exception.