FirstClown

firstclown at firstclown.us

Posts Tagged ‘tips’

Java Tips & Tricks: Unchangeable String

Unchangeable String

One of the fundamental data types in Java is the String. In fact, it's used so often that most people don't even think much about what a String is or how it works. But a String Object works like no other object in Java in two important ways; immutability and internment.

You Can't Touch This

Immutability means that an object can't be changed. Ever. You can't modify any of it's values in any way.

While this might not sound very useful, it actually allows Java to optimize how it handles Strings -- which is important since they're used so much in the language -- and brings a sense of security to using Strings. As we saw last week, when Objects are changeable, weird side effects can pop up when one variable changes an Object and all the other variables see the change and don't know what happened.

Strings sidestep this issue by never allowing you to change a String in place. In programming parlance, this means Strings never have side effects. So in this operation:

String a = "hello";
String b = a;

b = b.toUpperCase();

a and b are now pointing to two different String Objects. a is pointing to the original String of "hello" while b is pointing to a copy that's all uppercase of "HELLO". Even though a and b were pointing to the same String originally, the method toUpperCase() makes a copy and assigns the copy to b. This leaves a untouched. [1]

This property allows Strings to do another cool trick. They can Intern.

Lowly Paid College Students?

Interning is a method where you cache objects in memory to speed up creation of those objects. What that means is, all String literals are interned, and if you define the same literal, it will actually be the same Object. A little illustration:

String a = "hello";
String b = "hello";

It looks like a and b are pointing to two different Objects, but they're not. Here's why.

When Java sees the "hello" for variable a, it creates a new String Object with the value and assigns the reference to a. It then saves that Object in a table in memory, also called interning.

Then Java sees that b is getting a String with the value "hello". It checks it's intern table and sees it already has that Object created. Since Strings can't be changed, it doesn't hurt to just give that Object reference to b too, and so it does. Even though the programmer didn't explicitly say so, a and b are now pointing to the same Object in memory.

In fact, Java is so good at this, it'll assign to same Object to these variables too:

String c = "hel" +
              "lo";
String d = "h" + "e" + "l" + "l" + "o";

String is the only Class in Java that does interning in the JVM.

Next week we'll talk about how to use this knowledge to build better programs. (Hint: it has to do with memory management.)

[1]Strings aren't the only Objects that do this in Java. Can you think of any others?

Java Tips & Tricks: A Couple Pointers

A Couple Pointers

Many of you may have learned the following in Java 101, but I thought I'd repeat it just in case.

Most of the variables you'll use in Java are going to be Objects. So in the following code, we're creating three Objects:

BigDecimal number = new BigDecimal("9.5");
String welcome = "Hello";
Connection conn = DriverManager.getConnection(props);

The first case is using the standard constructor of a Class to create an Object, the second is creating a String via a String literal [1], and the third is creating an Object via a Factory (an Object that creates other Objects). All of these create an Object and puts it in the variable to the left.

Except I'm lying. Do you know where I'm lying?

Little Errand Boys

number, welcome, and conn aren't holding Objects, they're holding references to Objects. These are called pointers because they "point" to an Object and don't actually do anything except pass messages along to the Object they're pointing at. They're basically the Objects' errand boys. When you say something like:

number.toString();

You're basically saying "Hey, errand boy. Go ask your Object what it's string value is and then let me know." That becomes important when you consider that you can do this:

BigDecimal sameNumber = number;

sameNumber is now pointing to the exact same Object as number. That means that one Object has two errand boys. If I tell one errand boy to change the Object, then the other errand boy sees the change too, because it's the same Object! This can be confusing if you're not expecting it.

Cha-Cha-Cha-Changes

This has important repercussions when looking at methods calls. For instance:

public static void addItem(List listToAdd){
  listToAdd.add("Hello");
}

List group = new ArrayList();
System.out.println(group.isEmpty());  // Prints true

addItem(group);

System.out.println(group.isEmpty());  // Prints false

So even though group didn't add anything to the List Object, listToAdd did. Since they point to the same Object, both errand boys see the change. This is very important to remember when coding in Java.

Remember: Multiple variables can point to the same Object, so be careful changing them!

[1]Strings and arrays are the only Objects that can be created via a literal in our current version of Java.

Java Tips & Tricks: Double Trouble

At work, we've got a lot of new Java developers starting and I thought it might be a good idea to start up a little newsletter that, each week, will give little tips that Java programmers need to know but aren't usually told in classes or books. This is the first.


Double Trouble

Working with decimal numbers can be more complicated than it might seem. Many a Java programmer has been bitten by using doubles when calculating currency or another decimal value that relies on precision.

The problem

Let's say that we need to calculate a customer's bill. They used 80000.01 kWHs (big bill!) and we charge a dollar per kWH for this customer. To calculate that in cents, we just do:

double amount = 80000.01 * 100.0;

The answer we expect from this is 8000001. What we actually get, however, is 8000000.999999999! Why is this? Because doubles are inaccurate with large numbers. They just can't handle the calculation. They are actually made to be fast, not accurate.

So what should we do?

The Java language has anticipated this and created an object that can handle decimal numbers accurately. That class is BigDecimal. Using BigDecimals, our previous example would look like this:

BigDecimal kWH = new BigDecimal("80000.01");
BigDecimal price = new BigDecimal("100.0");
BigDecimal amount = kWH.multiply(price);

More complicated but we get the right answer of 8000001.00. We create the BigDecimal with Strings so that we keep the numbers safe from being rounded. If we called this as new BigDecimal(80000.01);, the number would be translated as a double first and then a BigDecimal, and we'll be passing it through an inaccurate format before getting it into a BigDecimal. We should avoid using doubles at all when dealing with important decimal numbers.

Remember: BigDecimal, not double or Double!

FirstClown is powered by WordPress
Entries (RSS) and Comments (RSS).