Jose Sandoval Google
 Resume     Book     Software     Drawings     Home     Subscribe to RSS feed Search Web Search josesandoval.com

Crazy Java Swing field validation
Tuesday, December 18, 2007

Typically, if you store anything to a database using a computer program, you want to ensure that the data is clean. For most applications, you want to validate user's input at the client level, at the business level, and at the database level. It's all about making sure users' mistakes are caught before storing invalid data.

When playing around with floats, doubles, and JTextFields (in swing), there are a couple of quirky things to pay attention to. For example, lets say you are expecting a decimal value (say a currency value), which should look like "100.45." Anything that is not a number should be rejected. As you know, JTextField objects can only give you String objects back when you ask for their content. As in:

JTextField jt = new JTextField("Jose Sandoval");
System.out.println(jt.getText());

If you run this snippet of code, you expect "Jose Sandoval" to print to the console. OK, nothing surprising here.

But what about a currency value? Those are funny--at least I think they're funny. Take a look the following code:

JTextField jtCurrency1 = new JTextField("100.50");
JTextField jtCurrency2 = new JTextField("100.5x");
JTextField jtCurrency2 = new JTextField("100.5d");
JTextField jtCurrency3 = new JTextField("100.5f");

try {
double d1 = Double.parseDouble(jtCurrency1.getText());
double d2 = Double.parseDouble(jtCurrency2.getText());
double d3 = Double.parseDouble(jtCurrency3.getText());
double d4 = Double.parseDouble(jtCurrency4.getText());
} catch (NumberFormatException e) {
e.printStackTrace();
}

Which one of those statements (if any) will throw a NumberFormatException?

Double.parseDouble() tries its best to return anything you give it as a double value. So a string that looks like "100.50" will return as the double value of "100.5." Cool, right?

So now that we know what Double.parseDouble() does, which of the variables above will have correct double values? Is it d1, d2, d3, or d4? None of them? Or all of them?

This is not a trick question, but if you are just starting to code in Java, you'd expect only d1 to have the right value of "100.5," as letters in numbers makes it just a string and not a number at all. Note that I don't mean to assume that you don't know Java, but I made the very assumption a while back, when Java was in version 1.0.x.

If you run the code, or know how a double is used in the language, you'll know that the only statement that will throw an exception is:

JTextField jtCurrency2 = new JTextField("100.5x");
...
double c2 = Double.parseDouble(jtCurrency2.getText());

In the case of c1, the String object looks like a real double value. In the cases for c3 and c4, things work because of how Java handles native values and how these values can be morphed into each other. I won't go into the details, but it has to do with the space required to store each value. When you cast from one type to the next what you are essentially doing is losing or gaining information depending of what you are doing: upcasting or downcasting (this is the same concept of object casting).

Aside from casting, why does it work? It works because in Java a float and a double can be interchanged to a certain extent--there are some caveats.

In code, a double value of "100.5" can be written as "100.5f" or "100.5d." To the user the value is the same, "100.5"; however, to the computer "100.5f" is stored in a space of this size "---------," assuming a dash (-) is a valid storage representation (in reality, they are bits or 0s and 1s, but that is harder to explain); now, the value of "100.5d" is stored in a space this big "------------------------------." Yes, a double requires more storage than a float, and it's obviously more accurate because the mantissa is longer (mantissa is all the number after the period, or what we normal people call decimal places).

Anyway, "100.5f" and "100.5d" are fine representation of a double value for "100.5." Therefore, the statements above are valid input for Double.parseDouble(). They become:

double d1 = 100.5f;
double d2 = 100.5d;

Now, does the other way around work? Yes and no:

float f1 = 100.5f;
float f2 = 100.5d; // <- this is not valid
If you have code like float f2 = 100.5d;, you will get a compiler error. Nonetheless, you can make it work if you implicitly cast that baby down to a float, as in float f2 = (float) 100.5d;.

Having letters as part of a number seems funny at first; however, it makes total sense when you need to distinguish between the precision of a float or a double. By the way, if you need real precision for currency calculation, you should be using BigDecimal instead of float or double.


12:41 AM | 0 comment(s) |

Comments:


This page is powered by Blogger. Isn't yours?

Guestbook
© Jose Sandoval 2004-2009 jose@josesandoval.com