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.
Related
I have been on this problem for hours but couldn't get close to solution.
Any help will be appreciated.
public static int enterTheAmount(){
int final LOTTO_PRICE = 1000;
int amount = Integer.parseInt(Console.readLine());
if(amount%LOTTO_PRICE!=0) throw new IllegalArgumentException();
return amount/LOTTO_PRICE;
}
Here, a user is going to enter a number, and if the number is not divisible by 1000, it throws an exception.
void validateTheEnteredAmount(){
final String INVALID_NUMBER = "1234";
InputStream in = new ByteArrayInputStream(INVALID_NUMBER.getBytes());
System.setIn(in);
assertThat(Application.enterTheAmount()).
isInstanceOf(IllegalArgumentException.class);
}
And I want to know when invalid number is entered, illegalArgumentException is thrown.
I used assertThat method & isInstanceOf methods to validate.
but for some reason, the test keeps failing..
Anyone with clues, please help
i used inputStream to store the number into the scanner.
On the console, it shows that illegalargumentexception is thrown, but the test fails..
You should use assertThrows to check this.
assertThrows(IllegalArgumentException.class, () -> Application.enterTheAmount());
This will assert that the method throws an exception. If it doesn't, the test will be considered as failed.
In the same situation I added a variable with Class type :
private Class exceptionClass;
And I will initialize it in a catch block as below:
public void updateBalance() {
try {
Account account = accountRepository.findById(id).get();
account.setBalance(balance);
accountRepository.save(account);
} catch (Exception e) {
exceptionClass = e.getClass();
}
}
And I wrote a method for my class that will check the result like below:
boolean hasObjectOptimisticLockingFailure() {
return this.exceptionClass == ObjectOptimisticLockingFailureException.class;
}
Then in my test method I checked it with below assertion statement:
assertTrue(account1.hasObjectOptimisticLockingFailure()
|| account2.hasObjectOptimisticLockingFailure());
I think you can do the same for your codes!!
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 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.
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!");
}
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.