How are Exceptions in java defined and how can I define my own?
As an example, we have ArithmeticException which prohibits us dividing by 0 and does not break the program.
What is try-catch's advantage to catching the same potential error with an if-else logic?
Furthermore, suppose I don't operate in the field of all integers, but specifically the field Z2 formed under addition in which 1+1=0.
Provided I have pre-defined an array of logic of operations, were I to do something like this:
try {
int a = 1;
int b = 1;
int c = a/(a+b);
} catch(myError e) {
//
}
where myError :
public class myError extends Exception {
public myError(String e) {
super(e);
}
}
But then, how does the try-catch clause know it is supposed to catch myError? What makes myError be what it is?
In other words: what defines, for example, ArithmeticException, to look for division by 0 among other things?
Alternatively I could throw new myError("something's wrong") , but that would defeat the whole point of defining a "custom" exception to begin with, since I could have thrown any exception like that.
Exceptions are just classes that extend class Throwable. Defining your own exception is done by creating a class that extends Throwable or one of its subclasses.
You can throw your own exception using throw new myError();.
ArithmeticException is a special exception thrown by the JVM when you divide by zero. It's not the exception that is looking for places where you divide by zero; it's how the / works. The / operator checks if the denominator is zero and will then throw the exception.
There is no way to add for example a check to the + operator so that it will throw whatever exception if the result of adding two numbers is zero. You'd have to write your own method to check and do this.
public int add(int a, int b) {
int result = a + b;
if (result == 0) {
throw new myError();
}
return result;
}
// Then use the add() method instead of +
try {
int a = 1;
int b = -1;
int result = add(a, b);
System.out.println(result);
} catch (myError e) {
System.out.println("The result was zero!");
}
Related
So I have code in Java, now I want that in C++. Everything is fine but I'm having trouble with exceptions.
In the 'Test' class in Java I have
try {
k = Integer.parseInt(args[i]);
}
catch (OutOfRangeException ex) {
System.out.println(args[i]+ ex.getMessage());
}
This is 'OutOfRange.java'
public class OutOfRangeException extends Exception {
public OutOfRangeException (String message) {
super (message);
}
}
And method from another class that throws that exception
public int number (int m) throws OutOfRangeException {
if (m < 0 || m >= arr.length) {
throw new OutOfRangeException(" - number out of range");
}
return arr[m];
}
};
I can't get the same effect with C++, I read a lot about it but still it doesn't work (I get 'dynamic exception specifications are deprecated in C++11' when it comes to 'throw' but I don't know how to get message in C++ either).
Is there a way I can do this like in Java?
I tried something like this:
In main:
try {
k = stoi(argv[i]);
}
catch (OutOfRangeException &e) {
cout << argv[i]<< endl;
}
Method:
int PrimeNumbers: number (int m) throw (OutOfRangeException) {
if (m < 0 || m >= sizeof(arr)) {
throw OutOfRangeException(" - number out of range");
}
return arr[m];
}
and constructor of OutOfRangeException
OutOfRangeException::OutOfRangeException(string message) {
cout<<message;
}
The thing is I get this 'dynamic exception...' error and I haven't found any other way to do it so I would be satisfied with it.
Dynamic exceptions specifications like
throw (OutOfRangeException)
in a function declaration have been deprecated since C++11 and were removed from C++ with C++17. Functions in modern C++ have only two exception specifications: Either can throw or cannot throw. The default is the former, so you don't need this specification at all.
int PrimeNumbers: number (int m) makes no sense, did you mean int PrimeNumbers::number (int m)?
sizeof(arr) does not do what you think it does. It returns the size of an object in bytes. I don't know how arr is declared, but it is almost surely wrong.
std::stoi throws the exception std::out_of_range if the parsed value does not fit into the type. It never throws your custom type OutOfRangeException.
I go over the all build-in exception in JDK, I only find SizeLimitExceededException when size exceed the expected length. However, if I want to throw an exception when size limit is below the expected length, there is no such built-in exception class that I can call?
Update:
SSN is 9 digits length. If input SSN is shorter than 9 digits length, then I want to throw this exception.
While using a fitting exception is good practice and you should spend some time to look for a fitting one (as you did), there is usually also no need to go over board with it.
In your example, I'd consider it totally fine if you'd just throw an new IllegalArgumentException("SSN is only of length <X> but length 9 is required"). It will fail the execution and give you a meaningful stacktrace.
Be aware that it is considered bad practice to use exception for control flow. So please never ever use something like
try {
person.setSSN(ssn);
catch (SSNTooShortException e) {
println("SSN too short! Please try again");
}
Instead use a custom validator to check SSN before setting it and only use the exception to guard against programming error.
if (!SSNFormat.matches(ssn)) { // <-- whoops condition is inverted
person.setSSN(ssn);
}
This snippet will hopefully fail soon in your (unit) test and you will know that your programming logic is flawed.
Of course, depending of your application, instead of using your custom validator, you could and should use one of the many validator frameworks (for an example, look at Hibernate's constraints, but virtually all big frameworks support validation in one or the other form).
Suppose there was a built-in JDK SizeLimitSubceededException (I just learned that subceeded is the opposite of exceeded). Would your code, which checks the length of the SSN throw one exception - SizeLimitExceededException - if the size exceeds the expected size, and another exception - SizeLimitSubceededException - if the size subceeds the expected size?
This would be awkward:
You would have to specify both exceptions in the throws clause of your method (assuming SizeLimitSubceededException would be a checked exception, same as SizeLimitExceededException).
The caller of your method would have to handle both exceptions.
And what if the size is right, but something else is wrong - for example, the SNN contains non-digit characters? Would you throw a third exception for that?
My point is that you'd be better off throwing a single type of exception from the method that sets the SSN.
If you want this to be a checked exception (which I suggest, in order to force the caller to handle it), I suggest defining your own custom exception - perhaps InvalidSSNException. This exception can have a constructor with several arguments - one of them the invalid SSN, another could be a boolean that indicates if the exception was thrown due to incorrect length.
Then your custom exception can produce an error message that matches the reason to the failure:
If the entered SSN had the wrong length (and it doesn't matter if it's too long or too short), the message would specify the expected length (9).
If the entered SSN had the correct length, the message would specify the valid characters (digits only).
Example:
class Person {
...
public setSSN (String ssn) throws InvalidSSNException
{
if (ssn == null) {
throw new InvalidSSNException (ssn, false);
}
if (ssn.length() != 9) {
// exception thrown as a result of invalid length
throw new InvalidSSNException (ssn, true);
}
for (char c : ssn.toCharArray()) {
if (c < '0' || c > '9') {
// exception thrown as a result of invalid character
throw new InvalidSSNException (ssn, false);
}
}
this.ssn = ssn;
}
...
}
Maybe you want something like IndexOutOfBoundsException. It is thrown to indicate that an index of some sort of data is out of range.
https://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html
You can create an exception as
public class UnderBottomException extends Exception {
public UnderBottomException(int dim, int param) {
super();
System.out.println("you entered a length of : " + dim + " whereas the minimum length expected is : " + param);
}
}
This exception will be implementable this way in your POJO :
public class Register {
private int[] registre;
private int minRange = 9;
public Register(int[] parametre) throws UnderBottomException {
if (parametre.length < this.minRange) {
throw new UnderBottomException(parametre.length, this.minRange);
}
else {
this.registre = new int[parametre.length];
for (int i = 0 ; i < this.registre.length; i++)
this.registre[i] = parametre[i];
}
}
public int[] getRegistre() {
return registre;
}
public int getMinRange() {
return minRange;
}
}
And finaly you use your object catching exception like this :
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8};
try {
Register monRegistre = new Register(a);
System.out.println("Nickel le sous registre de rang 2 = " + monRegistre.getRegistre()[1]);
}
catch(UnderBottomException e) {
}
}
}
Output :
you entered a length of : 8 whereas the minimum length expected is : 9
I have a class X that saves ints in an array:
public class X{
public int[] a;
public boolean[] allocated;
//constructor
public X(int len){
this.a = new a[len];
this.a = new allocated[len];
}
public void save(int tosave) throws ArrayStoreException{
int pos = 0;
for(int i=0; i<allocated.length; i++){
if(allocated[i] == true){
pos++;
}
}
if(pos == allocated.length){
throw new ArrayStoreExeption("no free space left");
}
a[pos] = tosave;
allocated[pos] = true;
}
}
And the class Y with save2 that I still need to implement...
public class Y extends X{
public void save2(int tosave){
// to be implemented
}
}
For save2 I want it to do the same as save with the exception, that if there is no more free space left or the ArrayStoreException occurs then I want the array to be doubled the size and then the parameter inserted to the array.
So if I do:
try{
super.save(tosave); // If no exception is thrown, does it save 'tosave'?
}catch(ArrayStoreExeption e){
System.out.println("noe free sapce left");
}
My first question is: if the try block does not trigger an exeption, will the code after catch block execute?
I don't know where to put the piece of code savely which doubles the array size if there is no more space left or the exeption is thrown.
Can someone help?
EDIT:
Can I place the code, that double the array inside the catch block?
the code you have posted has a number of syntax errors. I suggest you get those fixed and repost if this answer doesn't satisfy you.
yes you can implement your code to expand the array inside the catch block of the subclass. It will need to call the superclass's save method
your subclass should probably override the save method rather than create a new save2 method
using a boolean array doesn't make a lot of sense. Given you are not leaving any gaps wouldn't it be easier just to keep a single index of the first unallocated spot?
wherever possible keep your member variables private or protected. In this case if the subclass is going to expand the array then it will likely need to be protected. Better would be to make it private and have a protected method in the superclass to expand it.
Arrays.copyOf will do the expansion for you
So putting all that together:
class Fixed {
private int size;
private int[] store;
private int index = 0;
public Fixed(int size) {
this.size = size;
store = new int[size];
}
public void save(int value) throws ArrayStoreException {
if (index == size)
throw new ArrayStoreException();
store[index++] = value;
}
protected void expand() {
size *= 2;
store = Arrays.copyOf(store, size);
}
}
class Expandable extends Fixed {
public void save(int value) {
try {
super.save(value);
} catch (ArrayStoreException x) {
expand();
save(value);
}
}
}
If you prefer to avoid the recursion then you could use:
public void save(int value) {
try {
super.save(value);
} catch (ArrayStoreException x) {
expand();
try {
super.save(value);
} catch (ArrayStoreException x) {
throw new IllegalStateException("Cannot save after expansion");
}
}
}
You can put the code in finally block.
Regardless there is an exception or not, finally block do execute. (Exception : if called System.exit(0); in the try block.)
Conceptually, let's begin with
Try Block - You put the code here where you think there may be an ArrayStoreException.
Catch Block - This Block runs only if there is any exception thrown from try block.
You put the code, how it should handle. As per requirement, you can throw a message to console telling about the details of error, as in your case ArrayStoreException message and can prompt the user that you are going to double the capacity of ArrayList and can hence write the code for increasing the size of ArrayList
Finally Block - This block runs regardless of any exception is thrown or not. You can write the code for increasing the size of ArrayList here also. But, it will run even if there is no ArrayStoreException and the ArrayList has the capacity.
Note : If there is an exception thrown by the code, and is not handled or declared, so the code will stop running and no further code will run. But, if there is a proper handling of errors, the rest of the code runs.
For your case, I will suggest definitely to leverage the use of try-catch-finally block and put the code for doubling the size in catch block.
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.
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.