From String to any primitive type in 4 lines of code


Funkiness rating ★★★★★  Devviness rating ★★★★☆ 

 

Problem: i have some data in a text file, which contains 2 java.lang.Strings: the first one contains my data value, and the second one is the data type, i.e. “java.lang.Long”, “java.lang.Double”, etc.

How do i construct an object of the appropriate type containing the value in my text file?

Crappy solution: a loooong chain of if-else-if scanning through every supported type for choosing the appropriate parse* (Integer.parseInt, Double.parseDouble, etc.) method.

Why is this so crappy? Simply, because adding a supported type requires extending the if-else-if chain which may easily become too long and unreadable.

Funky solution: use the mighty powers of Java reflection!

Class objClass = Class.forName(type);
Class[] prototype = {String.class};
Constructor ctor = objClass.getConstructor(prototype);
return ctor.newInstance(new Object[]{value});

So what do these 4 lines do?
We get an instance of the Class object representing the class identified by the “type” String (the second string in our data file) and then we get the constructor which takes a single String as parameter, aka the constructor whose prototype is the one identified by our “prototype” variable; finally, we execute the constructor passing the value string.

Why is this so funky?

First of all, because it does in 4 lines of code what was done in a whoooole lot of lines in the crappy solution, but the very funky aspect of this solution is that it works not only with primitive types such as Integer, Long or Double, but also with any type which can be constructed with a String!

Veeeeeeeery funky!

Add This! Blogmarks BlogMemes BlueDot BlogLines co.mments Connotea del.icio.us de.lirio.us Digg Diigo Facebook Google Google Reader icio.de IndianPad Leonaut LinkaGoGo Linkarena Linkter Magnolia MyShare Yahoo! MyWeb Netscape Newsgator Newsvine reddit Rojo Segnalo Shadows Simpy SlashDot Spurl Startaid StumbleUpon TailRank Technorati ThisNext
  1. #1 by Peter - June 13th, 2009 at 19:56

    Wow! Nice! I will try that now .. ;-)

  2. #2 by dfa - June 13th, 2009 at 20:20

    I used this for many years:

    Class number;
    T zero = (T) number.getConstructor(String.class).newInstance(”0″);

  3. #3 by Ran Biron - June 14th, 2009 at 19:16

    Ugh. WRONG, WRONG!!!

    You’re circumventing caches, using reflection for simple lookups and giving up proper exceptions. Probably more, but I stopped counting.

    Use java.text.NumberFormat for proper string to number conversions, and add a single check for Double.NaN.

  4. #4 by Peter Lawrey - June 15th, 2009 at 07:35

    This is a good tip.

    The downside of the funky solution is that its is very inefficient. I have one helper method which does this ugly, but efficient way and I call that, and so hides the “crappy” way.

    If you want to support conversion of other types you may find that the String constructor is either not there or doesn’t do what you would want.

    Useful text conversions include Enum, and DateTime,a dn you can support String[], Integer[], List, Map

    I prefer to use the caches for Boolean, Integer, Long rather than creating new object every time.

    I treat “NaN” as NaN, and empty String as null in most cases.

  5. #5 by Raibaz - June 15th, 2009 at 13:18

    I know NumberFormat is better for string to number conversions, but i tend to prefer this approach whenever there is need for extensibility and the set of types to be created isn’t known in advance.

    Whenever the type set to be created is fixed, as the latest two comments have noticed, a more specific approach is probably better, but this one IMHO wins when generality is required.

(will not be published)
  1. No trackbacks yet.