0

I have a simple application which allows users to input a divisor, a divident and then calculates the quotient. I'm using vaadin as framework but I don't think that matters. So I've been thinking about the exceptions that can occurr and these are the ones i have identified: -Division by 0: ArithmeticException; -Users typing a string rather than a number: InputMismatchException Here is the class that creates the form and deals with the exceptions:

package my.vaadin.project.exceptionTest;


import java.awt.Component;
import java.util.InputMismatchException;

import com.vaadin.server.Page;
import com.vaadin.shared.Position;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.event.Action;

public class Calculation extends CustomComponent{
    final VerticalLayout vl = new VerticalLayout();
    final TextField dividend = new TextField();
    final TextField divisor = new TextField();

    final TextField result = new TextField();
    final Button resetButton = new Button("Reset");
    private int divisionResult = 0;
    Button button = new Button("Click Me");

    public Calculation(){
        dividend.setCaption("Enter the dividend:");
        divisor.setCaption("Enter the divisor:");

        result.setCaption("Result");
        result.setReadOnly(true); 
        button.addClickListener( new Button.ClickListener(){
            @Override
            public void buttonClick(ClickEvent event) {
                System.out.println("this is a test");   
                validateInputs();
            }            
        });
        resetButton.addClickListener(new Button.ClickListener(){            
            @Override
            public void buttonClick(ClickEvent event) {
                setDividend("");
                setDivisor("");             
                setResult("");
            }
        });
        vl.setMargin(true);
        vl.setSpacing(true);
        vl.addComponents(dividend, divisor, button, result );

    }//end of constructor
    public void validateInputs(){
        System.out.println("theDivisor is " + getDivisor() + " theDividend " + getDividend());
        try{
            divisionResult = ( Integer.parseInt(getDividend()) / Integer.parseInt(getDivisor()));
        }
        catch(ArithmeticException arithmeticException){
            System.err.println("Zero is an invalid denominator!");
            createError("Divisor can't be 0!! Please enter a number  > 0!");
        }
        catch(InputMismatchException inputMismatchException){
            System.err.println("The dividend or divisor are not a number! Please enter a valid number!");
            createError("The dividend or divisor are not a number! Please enter a valid number!");
        }
    }//end of validateInputs
    public String getDivisor(){     
        return divisor.getValue();
    }
    public String getDividend(){        
        return dividend.getValue();
    }
    public void setDivisor(String newDivisor){
        divisor.setValue(newDivisor);
    }
    public void setDividend(String newDividend){
        dividend.setValue(newDividend);
    }
    public void setResult(String newResult){
        result.setValue(newResult);
    }
    public void createError(String errorString){
        String error = errorString;
        Notification notif = new Notification(
                error,
                Notification.TYPE_ERROR_MESSAGE
            );
            notif.setDelayMsec(20000);
            notif.show(Page.getCurrent());
    }
}

I use the try catch statement when I calculate the quotient (but I haven't displayed the result as yet)

If I type 0 in the divisor then I get what I expect, an ArithmeticException is thrown and dealt with. However, if I type a string in the fields I would have thought that the InputMismatchException would take care of it but in fact this is the message I get in the console http://pastebin.com/z8U6bUYg I looked the NumberFormatException up and I'm not sure I understand what to do and why that happens. As you can see from the code I'm parsing the string to integers but it seems that the compiler doesn't like it. Do I have to add a catch statement and deal with the NumberFormatException too? Shouldn't the InputMismatchException be enough? Please let me know what you think

antobbo
  • 255
  • 1
  • 4
  • 21
  • 1
    Under what circumstances do `Integer.parseInt(String)` or integer division throw a `InputMismatchException`? That's only thrown by `Scanner`, [according to its documentation](https://docs.oracle.com/javase/7/docs/api/java/util/InputMismatchException.html). – Andy Turner Jul 10 '16 at 21:58
  • `NumberFormatException: For input string: "iuy"` suggests the input data, possibly collected through an input/textfield, you're trying to convert to a number is not actually a number, more specifically `iuy`. Looking at your code I don't see anything that could through the `InputMismatchException`, while `Integer.parseInt` does throw a `NumberFormatException` if it can't convert the string to a number, so you're probably _expecting_ the wrong exception... – Morfic Jul 10 '16 at 22:19
  • Possible duplicate of [What is a NullPointerException and how can I fix it?](http://stackoverflow.com/questions/39849984/what-is-a-nullpointerexception-and-how-can-i-fix-it) – xenteros Oct 13 '16 at 05:51

3 Answers3

1

If you look at the documentation of Integer.parseInt it is specified this:

Throws: NumberFormatException - if the string does not contain a parsable integer.

Instead, the InputMismatchException documentation specify this:

Thrown by a Scanner to indicate that the token retrieved does not match the pattern for the expected type, or that the token is out of range for the expected type.

Therefore the program seems to behave correctly and accordingly to the specifications.

This means you should catch NumberFormatException instead of InputMismatchException.

Loris Securo
  • 7,538
  • 2
  • 17
  • 28
0

Incompatibility issue

I have the same issue on Android Studio 0.8.7. But it is working fine with Android Studio 2.1. I think it should be fixed by updating Android Studio and Gradle Plugin to latest version.

good luck

Jayakrishnan
  • 4,457
  • 29
  • 29
-2

There are very rare occasions where you would catch RuntimeExceptions. Especially in your business code it's a bad pattern.

Make sure you validate your input values before you process them. You know that the divisor must not be zero, so, in your example, you should reject the input of zero for the divisor in your GUI, whatever it is (HTML input form, Swing TextField etc.).

At the latest, your setter setDivisor() MUST not accept a 0 and throw itself a Exception, e.g. an IllegalArgumentException.

Moreover, you should separate the concerns of your code. Don't mix the calculation of numbers with your GUI. The calculation should take place in another class that does not know about your GUI.

PS/EDIT: Trying to explain why catching RuntimeExceptions is not a good idea:

Taken from Oracle Docs: http://docs.oracle.com/javase/tutorial/essential/exceptions/catchOrDeclare.html

The third kind of exception is the runtime exception. These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs....

In your case the application CAN anticipate and recover from the fact that the user entered an invalid divisor. And even more, you should try your best to avoid letting the user enter invalid data.

Moreover, some other questions on SO, where people agree on the fact that catching RuntimeExceptions are a code smell.

Yes, catching any RuntimeException is almost always a code smell. The C2 Wiki seems to agree. Is Catching a Null Pointer Exception a Code Smell?

Another one from a more official source

Unchecked exceptions: RuntimeException also extends from Exception. However, all of the exceptions that inherit from RuntimeException get special treatment. There is no requirement for the client code to deal with them, and hence they are called unchecked exceptions. http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html?page=1

It goes on and on...

Likewise, programs must not catch RuntimeException, Exception, or Throwable. Few, if any, methods are capable of handling all possible runtime exceptions. https://www.securecoding.cert.org/confluence/display/java/ERR08-J.+Do+not+catch+NullPointerException+or+any+of+its+ancestors

Community
  • 1
  • 1
Jan B.
  • 6,030
  • 5
  • 32
  • 53
  • Why? The exception tells you it's invalid, and `parseInt()` already has to check that. Why repeat all that code? – user207421 Jul 10 '16 at 22:48
  • See the links to various websites that support my proposal. If you like we may discuss this issue more in detail beyond this thread. I'd be even happier if you withdrew the -1 vote unless you prove your theory right. – Jan B. Jul 10 '16 at 23:34
  • thanks guys, I will update my code and use the right exceptions then – antobbo Jul 11 '16 at 11:09