Tuesday, May 18, 2010

Strange String Comparisons Behavior in Java and the Literal String Pool


Got the following question from a student in my Introduction to Programming class.

I tried to compare two String variables with the == operator, and it wasn't working (have to use .equals()). I tried again right now, and it is working. I don't understand.

I suspect he ran into String Literal comparison quirk. Here is an example to demonstrate the point.

1    public class StringCompareTest 
2    { 
3       public static void main(String args[]) 
4       { 
5          String a = "123"; 

6          String b = "123"; 
7     
8          // 1) Comparing Strings in the literal String pool 
9          if(a == b) 
10            System.out.println("a equal b"); 

11         else 
12            System.out.println("a does not equal b"); 
13    
14         String c = new String("123"); 

15         // 2) Comparing String from literal String pool 
16         //    to a new String Object (not in the pool) 
17         if(a == c) 
18            System.out.println("a equal c"); 

19         else 
20            System.out.println("a does not equal c"); 
21    
22         // 3) Finally, what you should always use when 
23         //    comparing Objects, the equals method 

24         if(a.equals(c)) 
25            System.out.println("a equal c"); 
26         else 
27            System.out.println("a does not equal c"); 

28    
29      } 
30   } 
31   

In Java, String literals go into a memory pool call the Literal String Pool. The reason this is done is to save memory. If two different Strings are initialize to the same literal value (“123”). Java assigns the same reference to a String Object from the literal String Pool. In the above example, both a and b are assigned the same literal value of “123”. Rather than creating two String literal Objects, Java creates one and puts it in the literal String pool. Anytime it is used again, it can be reused from the literal String Pool. This can be misleading to new Java developers because the standard procedure is to tell students to use the equals() method to compare Objects for equality and only use == for primitives. In the case where the literal String already exists in the literal String pool, using == (shallow comparison) works because new Strings being assigned the same literal value will simply get the reference to a String from the literal String pool.

To further illustrate the difference, if a new String Object is created using the new operator and initialized in the constructor to the String “123”, then technically, both Strings a and c are equal. However, when we use == for the comparison, String a does not equal c. String c was initialized in the constructor to the literal value “123”. However, because String c was explicitly created using the new operator and therefore not part of the literal String pool, String comparison using == (shallow comparison) does not work.

In the end, step 3, we return to doing Object comparisons the right way. The last test use the equals() method to perform a deep comparison of the two String Objects (a and c). The output confirms that both Strings are equal. Moral of the story, stick with equals method for comparing Objects.

Monday, January 26, 2009

Autoboxing support C# VB (.NET) vs Java

I am currently doing .NET by day but still teaching Java for UCSD by night. During the last lecture, autoboxing came up. So I thought I would do a simple comparison between .NET and Java on how it handles Autoboxing.


// AutoboxTest.cs
using System;

class AutoboxTest
{
static void Main()
{
Console.WriteLine(22.ToString());
}
}


And like wise in VB


''' AutoboxTest.vb
Module AutoboxTest
Sub Main()
Console.WriteLine(22.toString())
End sub
End Module


So I thought I would give it a try in Java:


public class AutoboxTest
{
public static void main(String args[])
{
System.out.println(((Integer)22).toString());
}
}


Note: I could not get the simple form "22.toString()" to work unless I cast the literal to an Integer first. Score one for .NET.

No real numbers were harmed in this example. The number 22 was chosen because that is my hockey jersey number and paying tribute to the classic movie Casablanca.

Wednesday, December 3, 2008

First run with IPhone and RunKeeper

I love my IPhone. Best phone, hands down. I downloaded RunKeeper App last night. My first test run today. This app is frakkin awesome. I've found my new inspiration and motivation to stay in shape. The ROI on my IPhone is already beyond my expectations. Sample image below:

Friday, November 7, 2008

Time to blog again...

It's time to start blogging again. This post from Tim Bray was the motivation (kick in the butt) I needed. In addition, I have been using Twitter quite a bit lately and having lots of fun so the timing is right. The only difference is this time around, I am using blogger rather than roller. Blogging has come a long way and it looks like Blogger has plenty of toys to keep me busy. I'll use this blog as a way to share what I learn, what I see (pictures), and what I think is cool. Stay tuned...