How to check if String is parseable to Integer or Double?

This seems basic, right? In most cases it is, but as almost everything in Java this problem has its subtle pitfalls and problems. It is mainly because Java does not provide a simple utility method that can answer this question. Today I wanted to share with you several ways of solving this problem and describe their good and bad sides.

Why should you care?

Checking for that in many cases is unnecessary. If the format of data is defined and its contract states that the string is an integer you can just parse it and deal with unlikely exception that an error occurs. The problem is when there is no such a contract and you have to decide based on whether the string is an integer what actions to perform next. In that case plain try-catch check may be too expensive for you:

1:
2:
3:
4:
5:
6:
7:
8:
public boolean isInteger(String string) {
    try {
        Integer.valueOf(string);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

This method’s execution cost is high because of two factors: one is that to determine if string is an integer we have to do the whole parsing and throw away the result. Second is that we use exception throwing (which is expensive) to direct the program flow. The good thing about this code is its simplicity – you can at a glance say the method is correct.

Let’s use RegExp!

Much faster is to create a regular expression and use it to check whether string contains an integer or double. The good thing about this approach is that the regexp can be precompiled and used several times after:

1:
2:
3:
4:
5:
private static Pattern doublePattern = Pattern.compile("-?\\d+(\\.\\d*)?");

public boolean isDouble(String string) {
    return doublePattern.matcher(string).matches();
}

Unfortunately this method has important flaws: the pattern above will work for the most basic string representation of Double, but what about more advanced like “1.23E-12″. Even if you improve this pattern (belive me, its difficult) there are still some checks that it will not be able to perform, for instance checking if the integer is above Integer.MAX_INT.

What about Scanner?

There is a way of combining the two approaches shown above together: first check with regexp if string is possibly be an integer and if it seems to be one, try to perform the actual parsing. If the regexp is ‘good enough’ the number of false positives resulting in NumberFormatException will be acceptable. The good news is this approach is already implemented by a Scanner class. See the following example:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
public static void main(String[] args) {
    Scanner scanner = new Scanner("Test string: 12.3 dog 12345 cat 1.2E-3");

    while (scanner.hasNext()) {
        if (scanner.hasNextDouble()) {
            Double doubleValue = scanner.nextDouble();
        } else {
            String stringValue = scanner.next();
        }
    }
}

In essence Scanner breaks down the given string into tokens around whitespace and allows you to iterate trough them. It gives you useful access methods like ‘hasNextDouble()’ to check whether the next token is a Double or not and allows you to get it in a parsed version as a Double with ‘nextDouble()’ method.

Internals of Scanner show that it in fact combines both the regexp and exception catching methods, which makes it quite efficient. The downside is that the Scanner object itself is heavy and prepared to parsing larger text strings, so it may be ineffective if you need to use it on a simple strings like “123″.

Wait! It does not work for me!!

It is possible that you start using one of the methods above on a real life data and at some point things stop making sense… Why? Because we forgot about something important: the numbers are locale-sensitive and its string representation depends from country to country. For instance ten thousand in US is 10,000, in Poland 10 000 and in Italy 10.000. See that none of the methods above could successfully parse neither Polish or Italian numbers! What can you do in those cases? You have to use for parsing a NumberFormat class with specified locale:

1:
2:
3:
4:
5:
6:
private static NumberFormat italianDouble =
        NumberFormat.getNumberInstance(Locale.ITALIAN);

public boolean isItalianDouble(String string) {
    return (italianDouble.parse(string) != null);
}

Now you can finally see that 10,000 is a valid integer. Unfortunately with NumberFormat you get another set of problems – it is too liberal in parsing numbers! The method above will return true for 10,000 and false for both abc and x1, but it will return true also for 10abc as it looks only for a suffix in the string, not a total match.

Conclusion

As you can see none of the solutions shown above is perfect – each of the method aboves has its flaws and advantages. Because of that the choice which one is the best for you strongly depends on the context of your program. The important factors are: how often do you need to do a check like that, what is the false result ratio, whether you parse long human readable text or just few given values and whether you care about locale specific issues. It is also possible that in your code you’ll need a combination of them or to add some specific tweaks to one of them.

What is MessageFormat?

There are many ways to create a user readable message in Java, differing in the complication level, performance and capabilities. The easiest is to create the String message by using “+” operator and casting all message parameters to string. If the message is longer or more complicated you can use StringBuilder instead. For more advanced formating a String.format() method may be more useful.

Today I want to show you a Java class designed specially for advanced message formatting – MessageFormat. Its advantage over the already mentioned methods is that allows even more advanced value formatting, dependency on Locale and precompilation of the message.

The basic usage is very easy: create and compile a message pattern with placeholders in place of values. At runtime supply values and create a formatted final String. See the example:

1:
2:
3:
4:
  Object[] arguments = new Object[] {"John"};
  MessageFormat message = new MessageFormat("User {0} logged in.");

  System.out.println(message.format(arguments));

As a result of running this code you will get the following output: “User John logged in.”

Obviously you can do much more complicated things than that. The following example is a message that informs on the number of people living in specified city. The trick is that the message is in italian, so we specify the locale to get the italian-specific way of formating numbers (with a dot separating thousands instead of a coma):

1:
2:
3:
4:
5:
6:
7:
8:
9:
  Object[] arguments = new Object[] {
          12345, // argument 0 - number of people
          "Roma" // argument 1 - name of the city
  };

  MessageFormat message = new MessageFormat(
          "{0} persone vivono a {1}", Locale.ITALIAN);

  System.out.println(message.format(arguments));

The output of this code is: “12.345 persone vivono a Roma” – as expected number formatting is italian-specific.

Finally something really complicated – formatting of time, currency, number and also plural version of a noun:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
  Object[] arguments = new Object[] {
          "John",    // argument 0 - user name
          12.45,     // argument 1 - money paid
          3,         // argument 2 - amount of beers
          new Date() // argument 3 - date of transaction
  };

  MessageFormat message = new MessageFormat(
          "User {0} paid {1, number, currency} " +
          "for {2} at {3, time, full}", Locale.FRANCE);

  // fancy way to format the 2nd value - amount of beer bought
  ChoiceFormat beerFormat = new ChoiceFormat(
          new double[] {0, 1, 2},
          new String[] {"no beer", "one beer", "{2, number,0.0} beers"} );
  // set beerFormat to be used for argument number 2
  message.setFormat(2, beerFormat);

  System.out.println(message.format(arguments));

The code above will print “User John paid 12,45 € for 3,0 beers at 22 h 34 GMT”. By supplying different arguments and changing locale to US you might also get something like this: “User John paid $12.45 for one beer at 10:35:38 AM GMT”.

It is important to say that there is another way to use the ChoiceFormat above to format beer amount. For the purpose of readability we have created it as a separate object, but it could also be inlined in message format string:

1:
2:
3:
4:
  MessageFormat message3 = new MessageFormat(
          "User {0} paid {1, number, currency} " +
          "for {2, choice,0#no beer|1#one beer|2#{2,number,0.0} beers} " +
          "at {3, time, full}", Locale.FRANCE);

This is important as you may want to load message formats from a resource file, so all operations should be possible to be done in format text.

What is Java Dynamic Proxies API?

Let’s suppose you have some interface A and a class B implementing this interface. Suppose also that you want to wrap all method invocations on interface A and do something with them before passing them to class B. One of reasons you could need to do it is logging every method call to interface A. Instead of writing logging code directly in class B, you could create a separate invocation handler to do it for you. You can create such a handler very easily with Java Dynamic Proxies API.

Let’s demonstrate it here on a very simple example. We have an interface AdderInterface that defines a method for calculating a sum of two Integers:

1:
2:
3:
4:
5:
6:
public interface AdderInterface {
    /**
     * Returns a sum of a and b
     */
    public Integer add(Integer a, Integer b);
}

We also have an implementation of this interface. Class below will perform the addition and print a message on the way:

1:
2:
3:
4:
5:
6:
7:
8:
public class AdderImplementation implements AdderInterface {
    @Override
    public Integer add(Integer a, Integer b) {
        System.out.println
            ("[adder]\tCalculating sum of " + a + " and " + b + " ...");
        return a+b;
    }
}

Now when we finally have our interface and implementation ready the fun begins. We will show how to add some custom code, performing for example logging, directly before and after the method. In order to use Java Dynamic Proxies API we must implement a class that will be handling all the method calls before passing them to the real object they are supposed to be run on. This class must implement InvocationHandler interface with its single method ‘invoke’:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Proxy class that will catch method
 * invocations and wrap them with custom code
 */
public class Handler implements InvocationHandler {
    /**
     * Object that is being wrapped. In our case it
     * will be an instance of AdderImplementation.
     */
    Object obj;

    public Handler(Object obj) {
        this.obj = obj;
    }

    /**
     * When we invoke the method add() from our
     * main method, the call will be passed to this
     * method. Here we can run any custom code before
     * and after we really invoke the specified method.
     *
     * @param proxy The real proxy object. It is none
     *                 of the classes we implemented here.
     * @param m Invoked method
     * @param args Arguments passed to the
     *                invoked method
     * @return Result of invocation of the method
     *              m on object obj.
     */
    @Override
    public Object invoke(Object proxy, Method m, Object[] args)
        throws Throwable {
        Object result = null;
        try {
            System.out.println("[proxy]\tBefore calling method.");
            result = m.invoke(obj, args);
            System.out.println("[proxy]\tMethod returned " + result);
        } catch (Exception e) {
            //We could also put some code here if we want to do
            //anything special in case an Exception is thrown from
            //the inside of invoked method.
            throw e;
        }
        return result;
    }
}

Eventually we will have invoke() method run every time somebody calls add() method on interface AdderInterface, but as you see here class Handler has no mention of AdderInterface nor AdderImplementation. It is an important point because it means we could use class Handler for catching invocations of any arbitrary method on any interface.

In our example method invoke() is extremely simple and will just print a message right before and right after calling the specified method on the target object. Speaking about target object – it should be passed to the constructor of the Handler class, where it is stored in variable obj. Result of the invocation will be passed directly back to the caller (of course if there were no exceptions thrown).

Now we have already everything we need to get a proxy for our class AdderImplementation. Below is the main method that shows how to do it:

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
import java.lang.reflect.Proxy;

public class ProxyTestClass {
    public static void main(String[] args) {

        //We get an instance of a class implementing
        //AdderInterface from createAdder().
        AdderInterface adder = createAdder();

        //We run method 'add' directly on AdderInterface,
        //but the call will be caught by Handler.
        System.out.println("[main]\tCalling adder from main.");
        Integer result = adder.add(1, 2);
        System.out.println("[main]\tAdder returned " + result);
    }

    /**
     * Will create an instance of AdderImplementation, wrap it
     * using Handler class as invocation handler and return
     * as AdderInterface.
     *
     * @return Wrapped AdderImplementation
     */
    public static AdderInterface createAdder() {
        AdderInterface adder = new AdderImplementation();
        return (AdderInterface) Proxy.newProxyInstance(
                Handler.class.getClassLoader(),
                new Class[] { AdderInterface.class },
                new Handler(adder));
    }
}

Code directly responsible for getting the AdderInterface is separated into the method createAdder(). It uses method newProxyInstance() from class java.lang.reflect.Proxy to get a proxy for interface AdderInterface. As you see, the second parameter to that method is Class[]. It should hold an array of all interfaces that the created proxy will implement, so in our case it is only AdderInterface.class.

newProxyInstance() will dynamically create a class implementing the supplied interfaces. All the methods of that class will internally call the ‘invoke’ method from class Handler, which is the reason we had to supply an instance of it as the third parameter. We put also an instance of our class AdderImplementation as a parameter to Handler’s constructor, so that it knows which object’s method it should call.

Everything is now ready to go, so let’s push the Run button and see the output:

[main]	Calling adder from main.
[proxy]	Before calling method.
[adder]	Calculating sum of 1 and 2 ...
[proxy]	Method returned 3
[main]	Adder returned 3

As you see method add() from AdderImplementation was really invoked. Just before and just after that we see output from our Handler class.

Actually you will probably never have to it all by yourself. Instead, you could use a framework with an Aspect Oriented Programming solution, like for example Spring framework. AOP helps you deal with things called cross-cutting-concerns, which can be for example logging, security or transaction management. Dynamic Proxies are a way to implement AOP, so you would probably need them if you were going to create your own AOP-enabled framework.

Dynamic Proxies API is a powerful tool allowing creating proxies for classes in Java. You can read more about it on this Sun’s page or on this blog.