Tuesday, September 1, 2009

[Java] Mixing Generic with Legacy Code

This is kinda weird and troublesome. Even though as of Java 5 introduced generics to create type-safe collections, mixing this new kind of code with older non-generic one can be very tricky. Sun obviously did not want to make pre-Java 5 code redundant so it created a few ways to make these two types of code play nicely. For example:
List<String> l = new ArrayList<String>();  seems to create a type-safe arraylist polymorphically but mind you the JVM doesn't see the generic declaration at runtime; Using generics is ONLY a type of compile-time protection. But why ? Why did they do this ? The answer is simple - to mix this new code with legacy code; so at runtime the JVM only sees List l = new ArrayList(); . Look what happens if a developer is high and isn't careful when tampering with older code in the following example:

import java.util.*;

public class TestBadLegacy {
    public static void main(String[] args) {
          List<Integer> myList = new ArrayList<Integer>();
          myList.add(4);
          myList.add(6);
          Inserter in = new Inserter();
          in.insert(myList); // pass List<Integer> to legacy code
         
          /*
          for (int i=0;i<myList.size();i++){
              System.out.println(myList.get(i));
          }
          */
         
         
          for(Integer i:myList){
              System.out.println(i);
          }
         
         
       }
}
/*
this is the supposedly generic type-safe class, but check out below the legacy Inserter class which has a method that doesn't know
that a type-safe collection is being passed to it
*/

class Inserter {
      // method with a non-generic List argument
      void insert(List list) {
         list.add(new String("42")); // adds to the incoming list
    }
}

The result of running TestBadLegacy is:
4
6
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    at TestBadLegacy.main(TestBadLegacy.java:18)

Surprised ? you shouldn't. even though a String element has been added to an integer-only collection the compiler didn't complain because the adding took place in the legacy code but at runtime when we did the foreach we assigned at one poin an Integer reference to a String object so this resulted in a complete meltdown.

Bollocks!


Wednesday, August 26, 2009

[Java] Boxing, ==, and equals() tweak

It shouldn't be surprising that

Integer i1 = 1000;
Integer i2 = 1000;
if(i1 != i2) System.out.println("different objects");
if(i1.equals(i2)) System.out.println("meaningfully equal");

Produces the output:

different objects
meaningfully equal

How about this one:

Integer i3 = 10;
Integer i4 = 10;
if(i3 == i4) System.out.println("same object");
if(i3.equals(i4)) System.out.println("meaningfully equal");

This example produces the output:

same object
meaningfully equal

Yikes! The equals() method seems to be working, but what happened with == and != ? Why is != telling us that i1 and i2 are different objects, when == is saying that i3 and i4 are the same object? In order to save memory, two instances of the following wrapper objects (created through boxing), will always be == when their primitive values are the same:
■ Boolean
■ Byte
■ Character from \u0000 to \u007f (7f is 127 in decimal)
■ Short and Integer from -128 to 127


Source: Sierra & Bates SCJP 6 Study Guide , Chapter 3

Tuesday, August 18, 2009

How to instal Intellij IDEA on Ubuntu

1. get your copy from here http://www.jetbrains.com/idea/download/
2. Unpack the idea-8.1.3.tar.gz file using the following command: tar xfz idea-8.1.3.tar.gz
3.
[this is the tricky part] Edit idea.sh from the bin subdirectory by adding the jdk 6 home directory to the variable IDEA_JDK (i.e. IDEA_JDK=/usr/java/jdk1.6.0 , depends on where you've placed the sdk )

Jah bless

make GRUB menu reappear after installing UBUNTU (having a vista installation to start with)

I had Ubuntu 9.04 (Jaunty) installed on a 80 gigs partition on my pc beacuse i was starting to get sick of Vista but after my first reboot, the system booted vista automatically without prompting me with the boot (grub) meu at startup. I've researched this over the web and came up with the following solution:

1. Use ubuntu live cd to boot into the unix system
2. open a terminal via Accesories menu
3. type "sudo grub"
4. type "find /boot/grub/stage1" - this will return a result, in my case it was (hd0,4)
5. type "root (hd?,?)" - in my case i typed root (hd0,4)
6. type "setup (hd0)"
7. quit and reboot

have a nice day

Sunday, July 5, 2009

GWT ftw

The google web toolkit provides a kickass infrastructure for creating ajax-powered web apps right from java code. The gwt compiler will transform the java into javascript and the results are stunning. Here are 2 very sweet links for easy learning the basics of GWT, mainly the RPC (remote procedure call) feature:
http://www.vogella.de/articles/GWT/article.html
http://developerlife.com/tutorials/?p=125

Friday, May 8, 2009

Misinterpretation (or the reason why FAQ sounds like "fuck you")

I was trying to get the size of a JDBC result set without the usage of some gay code like "while(rs.next()) { //increment an index}" or worse, creating another statement with the query "select count(*) .... " to retreive only the number of rows from the targeted table.
Even though at first you might want to try resultSet.getFetchSize() , it will not get the "fetch size" specified in the nomenclature, i.e. the number of rows you seek. A closer peek at the jdbc documentation states that getFetchSize() "Retrieves the number of result set rows that is the default fetch size for result sets generated from this Statement object" .
The solution for this ? there is no predefined method in the Statement metadata to return the result set size without parsing it... you may need to choose one of the (gay) methods specified above or find some other.

Saturday, May 2, 2009

parse me again blues

Having the DB entity "Message" with ID and text, i was returning with the entity manager a collection of the form Set<Message> . After obtaining this set i needed to line these messages in a forum thread i was building. The problem isn't that i couldn't get the messages but the message list was not sorted by id (which i recon is by default because that's how result sets go), so everytime i refreshed my forum page, i got those messsages in a different order.
My solution? Altough redneck-ish, i've manually sorted the Set<Message> collection before returning it :p