Unable to catch Arithmetic exception (Catching IllegalArgumentException fine though) - java

Please have a look at mine constructor below, I'm creating a Fraction from a String:
public Fraction(String str)
{
if(str.isEmpty())
{
throw new IllegalArgumentException("The str (String) parameter cannot be empty!");
}
int[] fractionData= new int[2];
String[] data = str.split("/");
try
{
if(data.length==0)
throw new IllegalArgumentException("The str (String) parameter cannot be empty");
}
catch (IllegalArgumentException ex)
{
System.out.println(ex.toString());
}
try
{
fractionData[0] = Integer.parseInt(data[0]);
}
catch (IllegalArgumentException ex)
{
System.out.println(ex.toString());
}
try
{
fractionData[1] = Integer.parseInt(data[1]);
if(fractionData[1]==0) throw new ArithmeticException("Denominator can't be 0");
}
catch (ArithmeticException ex)
{
System.out.println(ex.toString());
}
fractionData = normalize(fractionData[0],fractionData[1]);
this.numerator = fractionData[0];
this.denominator = fractionData[1];
}
I'm catching the IllegalArgumentException fine, but fail to catch the ArithemticException. I can test both successfully
#Test(expected=IllegalArgumentException.class)
public void testIllegalArgumenException() throws IllegalArgumentException
{
Fraction g = new Fraction("");
}
#Test(expected=ArithmeticException.class)
public void testArithmeticException() throws ArithmeticException
{
Fraction g = new Fraction(1/0);
}
Thanks the comments from #xp500 I've changed my code to:
public Fraction(String str)
{
if(str.isEmpty()) throw new IllegalArgumentException("The str (String) parameter cannot be empty!");
int[] fractionData= new int[2];
String[] data = str.split("/");
if (data.toString().matches("[a-zA-Z]+")) throw new NumberFormatException("only numbers allowed in the string");
fractionData[0] = Integer.parseInt(data[0]);
fractionData[1] = Integer.parseInt(data[1]);
if(fractionData[1]==0) throw new ArithmeticException("Denominator can't be 0");
fractionData = normalize(fractionData[0],fractionData[1]);
this.numerator = fractionData[0];
this.denominator = fractionData[1];
}
It doesn't quote "only numbers allowed in the string", but stops initializing the Fraction as 0/0 in case String with letters is used to initialize the Fraction and throws the other exceptions with quoted text. The lesson for me is: DON'T CATCH EXCEPTIONS UNLESS YOU'RE ACTUALLY DOING SOMETHING WITH THEM

Yo are catching ArithmeticException but you are not retrowing it(like other exceptions)

A couple of comments about the code.
Your usage of the exceptions is making the code unreadable and hard to follow. You should try to use less try catch blocks. I think it would be better if you wrote something along the lines of
if (data.length==0) {
System.out.println(ex.toString());
throw new IllegalArgumentException("The str (String) parameter cannot be empty");
}
and not catch that exception, since you want to tell the caller that an exception occured.
Also, fractionData[0] = Integer.parseInt(data[0]); throws a NumberFormatException, not IllegalArgumentException
The ArithmeticException isn't being thrown since you are catching it inside the constructor, and not rethrowing it. Please note that, after catching it, your fraction will be initialized in an invalid state, since
fractionData = normalize(fractionData[0],fractionData[1]);
this.numerator = fractionData[0];
this.denominator = fractionData[1];
will be executed. Again, you might want to rewrite those lines for something like
if(fractionData[1]==0) {
System.out.println(ex.toString());
throw new ArithmeticException("Denominator can't be 0");
}
You don't need to write throws Exception, in your test methods, since you are expecting an exception to be thrown, the method itself won't throw that exception.
I hope that helps!

Related

Exception Handling in Java to have Java best practices

I have a Java method like below:
private boolean getBooleanProperty(String property, String defaultValue) {
boolean result = false;
try {
result = Boolean.parseBoolean(properties.getProperty(property, defaultValue));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
I know that the way I am handling the exceptions in above method is not correct and looking for the way to have those more aligned with the Java standards and best practices.
Similarly for the method below:
public void getStatusAndAnnotation(ITestResult result) {
try {
HashMap<Object, Object> map = new HashMap<>();
Method method = result.getMethod().getConstructorOrMethod().getMethod();
TestInfo annotation = method.getAnnotation(TestInfo.class);
try {
//add id removing the first character of the annotation (e.g. for C12034, send 12034)
if(annotation!=null) {
map.put("id",annotation.id().substring(1));
}
}catch (NullPointerException e){
e.printStackTrace();
}
if (result.getStatus() == ITestResult.SUCCESS) {
map.put("result", 1);
} else if (result.getStatus() == ITestResult.FAILURE) {
map.put("result", 9);
} else if (result.getStatus() == ITestResult.SKIP) {
map.put("result", 10);
}
if (annotation != null) {
if(annotation.trDeploy() && !map.get("id").equals(null) && !map.get("id").toString().isEmpty())
{
ApiIntegration.addTestResult(map);
}
else System.out.println("Deploying result was canceled, because test has annotation \"trDeploy: false\" or \"id\" has no value");
}
} catch (SecurityException | IOException
| ApiException | NullPointerException e) {
e.printStackTrace();
}
}
How do I handle these different exceptions to align with the best practices?
What I typically do is let the compiler/IDE tell me what exceptions I need to catch unless you want to catch an exception for a specific reason. That way, I can code without catching unnecessary exceptions and my code is cleaner.
These type of Exceptions are called Checked Exceptions
"In the Java class hierarchy, an exception is a checked exception if
it inherits from java.lang.Exception, but not from
java.lang.RuntimeException. All the application or business logic
exceptions should be checked exceptions."
Example:
try
{
// open a file (Compiler will force to either catch or throw)
}
catch (IOException ioe)
{
ioe.printStackTrace();
// need to make a decision on what to do here
// log it, wrap it in a RuntimeException, etc.
}
As for Unchecked Exceptions
"Unchecked, uncaught or runtime exceptions are exceptions that can be
thrown without being caught or declared"
Example:
String x = null;
// this will throw a NullPointerException
// However, you don't need to catch it as stated in some the comments
x.toString();
What you should do is prevent it
if (x == null)
{
x = "some default value"; // prevent the exception from happening.
}
x.toString();
Does this mean you should never catch a RuntimeException
No, of course not. It depends on the scenario.
Take this example:
String number = "12345";
// You don't know if number is a valid integer until you parse it
// If the string is not a valid number, then this code will
// throw an Exception
int i = Integer.parseInt(number);
Instead you can catch a NumberFormatException. Again, this is a form of prevention.
int i = 0; // some default
try
{
i = Integer.parseInt(number);
}
catch (NumberFormatException nfe)
{
// Good practice to log this, but the default int is fine.
}
Some Best Practices
Do not catch exceptions unless the compiler forces you to.
If you are catching a checked exception, then log it. You can also wrap it in a RuntimeException if you want it to percolate up the call stack.
If you want to catch a RuntimeException, then do so with a purpose (i.e. you can set a default and prevent the error all together.)
Don't have a chain of methods all throwing a checked Exception up the stack trace. This is very messing and forces all calling methods to either catch or throw the checked exception.
Catching a RuntimeException just to log it really doesn't have much of a purpose. Unless you are logging it in a catch all location.
Catch-All Example:
try
{
// entry point to application
}
catch (Throwable t)
{
// let all exceptions come here to log them
}

How to throw an exception if parsing with Long.parseLong() fails?

I am trying to write some kind of a stack calculator.
Here is a part of my code where I am handling a push command. I want to push integers only, so I have to get rid of any invalid strings like foobar (which cannot be parsed into integer) or 999999999999 (which exceeds the integer range).
strings in my code is a table of strings containing commands like POP or PUSH, numbers, and random clutter already split by white characters.
Main problem:
I've got difficulties with throwing an exception for long parseNumber = Long.parseLong(strings[i]); - I don't know how to handle the case, when strings[i] cannot be parsed into a long and subsequently into an integer.
while (i < strings.length) {
try {
if (strings[i].equals("PUSH")) {
// PUSH
i++;
if (strings[i].length() > 10)
throw new OverflowException(strings[i]);
// How to throw an exception when it is not possible to parse
// the string?
long parseNumber = Long.parseLong(strings[i]);
if (parseNumber > Integer.MAX_VALUE)
throw new OverflowException(strings[i]);
if (parseNumber < Integer.MIN_VALUE)
throw new UnderflowException(strings[i]);
number = (int)parseNumber;
stack.push(number);
}
// Some options like POP, ADD, etc. are omitted here
// because they are of little importance.
}
catch (InvalidInputException e)
System.out.println(e.getMessage());
catch (OverflowException e)
System.out.println(e.getMessage());
catch (UnderflowException e)
System.out.println(e.getMessage());
finally {
i++;
continue;
}
}
Long.parseLong(String str) throws a NumberFormatException if the string cannot be parsed by any reason. You can catch the same by adding a catch block for your try, as below:
catch ( NumberFormatException e) {
System.out.println(e.getMessage());
}
No need to worry. Long.parseLong() throws a NumberFormatException if it got other than a Number.
After reading your comments and answers I was able to come up with such a solution (this code is embedded inside the outside try-catch.)
if (strings[i].equals("PUSH")) {
// PUSH
i++;
if (strings[i].length() > 10) {
throw new OverflowException(strings[i]);
}
try{
parseNumber = Long.parseLong(strings[i]);
if (parseNumber > Integer.MAX_VALUE) {
throw new OverflowException(strings[i]);
}
if (parseNumber < Integer.MIN_VALUE) {
throw new UnderflowException(strings[i]);
}
number = (int)parseNumber;
stack.push(number);
}
catch (NumberFormatException n){
throw new InvalidInputException(strings[i]);
}
}

How do I display an exception?

I am checking if number the user entered is Zeckendorf and I want to display an exception if it is not, how do i do that? Also how do I convert the Zeckondorf to its decimal equivalent?
import java.util.Scanner;
public class IZeckendorfNumberConvertor {
static String number;
int zeckonderEquivalent;
static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
convertToZeckonderNumber();
isTrueZeckonderNumber();
}
private static boolean isTrueZeckonderNumber() {
System.out.println("Enter a Zeckonder Number:");
number = scanner.nextLine();
if (number.equals("10100"))
{
return true; }
else if (number.equals("010011") || number.equals("010100"))
{
return false; }
return false;
}
private static void convertToZeckonderNumber() {
}}
I advise you not to display an exception (i.e. trace and such) as it is very user Unfriendly.
You can use the throw syntax to throw a proper exception :
throw new Exception("Given number is not a Zeckendorf number");
but be sure to catch it and display a nice and clean message :
try {
// Your input code goes here
} catch (Exception e) {
System.out.println(e.getMessage());
}
Another easier option will be to just check the return value of the method and print the results accordingly.
I will recommend to use the latter solution as exceptions are used when something bad and unexpected happens in your program and you want to handle it gracefully. In your case the behavior is expected (i.e. user giving a wrong number) so checking the return value will be much clean and easier.
Use try catch block for catch an exception
try {
} catch (Exception e) {
e.printStackTrace();
}
Also use throw for throw a new exception
Assuming to really do want to display the exception, and not a more user friendly message, the first step is probably to get the exception as a string. Then you can do what you like with that string (echo to console, place in a javax.swing.JTextArea, email it, etc).
If you just want the message from the exception, then getMessage() will do:
try { ... }
catch(FooException e) {
String msg = e.getMessage();
}
However, if you want the whole exception, stack trace and all, you'll want something like this:
public static String stackTrace(Exception e) {
StringWriter w = new StringWriter();
e.printStackTrace(new PrintWriter(w));
return w.toString();
}
// ...
try { ... }
catch(FooException e) {
String st = stackTrace(e);
}
If you just want to echo the full stack trace to the console, there is the printStackTrace(), no-arg method:
try { ... }
catch(FooException e) {
e.printStackTrace();
}
If you want to take more control of the presentation of the stack trace you can get the details with:
try { ... }
catch(FooException e) {
StackTraceElement[] stes = e.getStackTrace();
// Do something pretty with 'stes' here...
}
You can just print a error message to the user saying that the input is wrong using a simple if.
if(yourCondition){
// Happy scenario
// Go shead
}else{
// Error Scenario
System.out.println("Error. Invalid Input.");
// If you persist to throw an exception, then you can do something like this
// throw new Exception("Exception Explanation"); // I've commented this, but you can uncomment it if needed
// But the advice is to display an error message, than throw a exception.
}
And regarding the conversion, you can convert binary to decimal like this
int i = Integer.parseInt(binaryString, 2); // 2 indicates the radix here, since you want to convert from binary.
With this code snippet you can convert the String into an integer :
int numberAsInt;
try {
numberAsInt = Integer.parseInt(number);
} catch (NumberFormatException e) {
//Will throw an Exception
}
If you want to create your own Exception class, you can do it like shown here or just throw a RuntimeException with
throw new RuntimeException("Your Message");
My opinion, you can try some thing like following
public static void main(String[] args) {
if(!isTrueZeckonderNumber()){
// your message should goes here
System.out.println("Your message");
}
}
If you really want to throws an exception do following
private static boolean isTrueZeckonderNumber() throws Exception{
System.out.println("Enter a Zeckonder Number:");
number = scanner.nextLine();
if (number.equals("10100")) {
return true;
} else{
throw new Exception("your message");
}
}
What do you mean you want to display an exception?
I would suggest just giving the user feedback instead, as exceptions are used more commonly for EXCEPTIONAL actions that are not supposed to happen.
However if you do want to, you can print a message explaining what happened.
try {
} catch (Exception e) {
System.out.println(e.getMessage());
}

How to handle try/catch and throw with Junit test

Im kinda new to handling exceptions in Java with Junit, a little guidence would be much appreciated.
What I am trying to do:
I surround the creation of the new CustomObject with a try as the user can pass in a String that will not match an enum when we call valueof(). I want to be able to catch an exception here, which I am, though I am told: "A catch statement that catches an exception only to rethrow it should be avoided.". There must be a better way to handle this?
If the new object has the correct enum then I call isValidObject, which returns a boolean. If the Integer is not valid then I throw an exception.
My test has a #Test(expected = AssertionError.class) and is passing.
Is there a better/cleaner way to use the exceptions?
I have the code below:
private CustomObject getObjectFromString(String objectDataString) {
if (objectDataString != null) {
String[] customObjectComponents = objectDataString.split(":");
try {
CustomObject singleObject = new CustomObject(EnumObjectType.valueOf(customObjectComponents [0]),
Integer.parseInt(customObjectComponents [1]));
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + EnumObjectType.valueOf(customObjectComponents [0]) + ":"
+ Integer.parseInt(customObjectComponents [1]));
}
} catch (IllegalArgumentException e) {
throw e;
}
}
Oh, and if anyone can recommend anything good to read about exception handling, that would be great.
A catch statement that catches an exception only to rethrow it should be avoided.". There must be a better way to handle this?
Yes, simply remove the try catch. Your code is equivalent to:
private CustomObject getObjectFromString(String objectDataString) {
if (objectDataString != null) {
String[] customObjectComponents = objectDataString.split(":");
CustomObject singleObject = new CustomObject(EnumObjectType.valueOf(customObjectComponents[0]),
Integer.parseInt(customObjectComponents[1]));
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + EnumObjectType.valueOf(customObjectComponents[0]) + ":"
+ Integer.parseInt(customObjectComponents[1]));
}
}
}
That code will throw an IllegalArgumentException if the value passed to your enum.valueOf() is not valid or if your isValidCustomObject method returns false.
Note that it might also throw an IndexOutOfBoundException if the string does not contain a : which you probably want to test before calling customObjectComponents[1]. And it might throw NumberFormatException too.
And you seem to accept a null String as a valid entry, which is probably not a good idea (depends on your use case obviously).
I would probably have written it that way:
private CustomObject getObjectFromString(String objectDataString) {
Objects.requireNonNull(objectDataString, "objectDataString should not be null");
String[] customObjectComponents = objectDataString.split(":");
if (customObjectComponents.length != 2) {
throw new IllegalArgumentException("Malformed string: " + objectDataString);
}
EnumObjectType type = EnumObjectType.valueOf(customObjectComponents[0]);
try {
int value = Integer.parseInt(customObjectComponents[1]);
} catch (NumberFormatException e) {
throw new IllegalArgumentException(customObjectComponents[1] + " is not an integer);
}
CustomObject singleObject = new CustomObject(type, value);
if (isValidCustomObject(singleObject)) {
return singleObject;
} else {
throw new IllegalArgumentException("Unknown custom object type/value: " + type + ":" + value);
}
}
And finally, it would probably make sense for the CustomObject's constructor to check whether its arguments are ok or not by itself, instead of having to call a separate isValid method. The last block would then simply be:
return new CustomObject(type, value);
which would throw an IllegalArgumentException from the constructor if required.

continuing execution after an exception is thrown in java

I'm trying to throw an exception (without using a try catch block) and my program finishes right after the exception is thrown. Is there a way that after I throw the exception, to then continue execution of my program? I throw the InvalidEmployeeTypeException which I've defined in another class but I'd like the program to continue after this is thrown.
private void getData() throws InvalidEmployeeTypeException{
System.out.println("Enter filename: ");
Scanner prompt = new Scanner(System.in);
inp = prompt.nextLine();
File inFile = new File(inp);
try {
input = new Scanner(inFile);
} catch (FileNotFoundException ex) {
ex.printStackTrace();
System.exit(1);
}
String type, name;
int year, salary, hours;
double wage;
Employee e = null;
while(input.hasNext()) {
try{
type = input.next();
name = input.next();
year = input.nextInt();
if (type.equalsIgnoreCase("manager") || type.equalsIgnoreCase("staff")) {
salary = input.nextInt();
if (type.equalsIgnoreCase("manager")) {
e = new Manager(name, year, salary);
}
else {
e = new Staff(name, year, salary);
}
}
else if (type.equalsIgnoreCase("fulltime") || type.equalsIgnoreCase("parttime")) {
hours = input.nextInt();
wage = input.nextDouble();
if (type.equalsIgnoreCase("fulltime")) {
e = new FullTime(name, year, hours, wage);
}
else {
e = new PartTime(name, year, hours, wage);
}
}
else {
throw new InvalidEmployeeTypeException();
input.nextLine();
continue;
}
} catch(InputMismatchException ex)
{
System.out.println("** Error: Invalid input **");
input.nextLine();
continue;
}
//catch(InvalidEmployeeTypeException ex)
//{
//}
employees.add(e);
}
}
If you throw the exception, the method execution will stop and the exception is thrown to the caller method. throw always interrupt the execution flow of the current method. a try/catch block is something you could write when you call a method that may throw an exception, but throwing an exception just means that method execution is terminated due to an abnormal condition, and the exception notifies the caller method of that condition.
Find this tutorial about exception and how they work - http://docs.oracle.com/javase/tutorial/essential/exceptions/
Try this:
try
{
throw new InvalidEmployeeTypeException();
input.nextLine();
}
catch(InvalidEmployeeTypeException ex)
{
//do error handling
}
continue;
If you have a method that you want to throw an error but you want to do some cleanup in your method beforehand you can put the code that will throw the exception inside a try block, then put the cleanup in the catch block, then throw the error.
try {
//Dangerous code: could throw an error
} catch (Exception e) {
//Cleanup: make sure that this methods variables and such are in the desired state
throw e;
}
This way the try/catch block is not actually handling the error but it gives you time to do stuff before the method terminates and still ensures that the error is passed on to the caller.
An example of this would be if a variable changed in the method then that variable was the cause of an error. It may be desirable to revert the variable.

Categories

Resources