Tag Archive for 'java'

Java Tips: Using generic correctly

Generic is very powerful tools, it allows us to get errors that usually only happen in runtime to compile time like the usual type error.

Generic is also very tempting and in normal case, is very easy to use in daily programming. But without a good thinking, we normally will lose the actual power of generic. Let’s we start with this bad news.

The last article I referred on article Java Tips: Iterate and cast is one example where we wrote a Java code using generic but not optimally. The code is as follow:

@SuppressWarnings("unchecked") public static <X> X cast(Object o) {
    return (X) o;
}

What’s wrong with that? PPOW show the wrong cases to us.

Number telephoneNumber = cast("1234567");

session.setAttribute("digits", setOfDigits);
List<Character> characters = cast(session.getAttribute("digits"));

String authorName = cast(session.getAttribute("authorId"));

The errors that we usually get in compile time are missed and can only be get in runtime.

How to make it correct? It is actually pretty simple if we think it through. The essence of casting is to specify that certain superclass that we have is actually a subclass. This relationship is important. Knowing that we know that the argument of the method should be superclass of the result, and not an arbitrary object. So we can fix our method cast like following.

@SuppressWarnings("unchecked") public static <T, X extends T> X cast(T o) {
	return (X) o;
}

And now try all the cases PPOW suggested and we will get an error in compile time. That’s good!

The last case PPOW suggested in the article is not really valid because even using a not tricky techniques, the error will only be happen in runtime. These codes compile correctly but all have problem in runtime.

Using original code:

// Because of an error we cast it to a map of String to String
Map<String, String> badMap = cast(session.getAttribute("map"));

// we pass the map between many objects and doing many operations on it
String s1 = badMap.get(1);
badMap.put("2", "2");
String s2 = badMap.get("2");
String s3 = badMap.get(2);
String s4 = badMap.get(123);

Using modified code:

// Because of an error we cast it to a map of String to String
Map<String, String> badMap2 = cast2(session.getAttribute("map"));

// we pass the map between many objects and doing many operations on it
String s1a = badMap.get(1);
badMap.put("2", "2");
String s2a = badMap.get("2");
String s3a = badMap.get(2);
String s4a = badMap.get(123);

Using normal cast:

// Because of an error we cast it to a map of String to String
Map<String, String> badMap3 = (Map<String, String>)(session.getAttribute("map"));

// we pass the map between many objects and doing many operations on it
String s1b = badMap.get(1);
badMap.put("2", "2");
String s2b = badMap.get("2");
String s3b = badMap.get(2);
String s4b = badMap.get(123);

As you can see, generic is easy to implement, but to implement it correctly is not that easy. I really suggest to read the white print of generic which honestly, I still don’t understand the whole of it. The latest edition of Effective Java also has some tips to work with generic.

Learn generic, it is worth it!

My Eclipse Code Formatter

A consistent code format across the project is one sign of a maintainable project. Almost all of Java IDEs provide a way to format your code, but in my opinion, Eclipse does deliver the most customizable Java formatter. Many aspects from the code can be configured using the tools.

Lately the format used by Kevin Bourrillion caught my eyes. Among other things, he chose to use method annotation without any line break. So instead of:

    @Deprecated
    @Override
    public void bar(@SuppressWarnings("unused") int i) {
        @SuppressWarnings("unused")
        int k;
    }

he used:

    @Deprecated @Override public void bar(@SuppressWarnings("unused") int i) {
        @SuppressWarnings("unused")
        int k;
    }

And for an empty constructor or an empty method, instead of the standard:

private Casts() {
}

he used:

private Casts() {}

At first, I don’t really like it, but after working with Google Collections, this format seems make sense. It reduce the number of lines and make the code a lot easier to read. Yes, the line will be longer, but today’s programmers seem to use a big monitor anyway, right?

Now I know that he uses IDEA for his IDE and he doesn’t publish his code style in the Google Collections or Google Guava, but I also don’t want to copy his style 100%, so I made my own custom style and publish it in GitHub: http://github.com/enefem/eclipse-config

You can download the style there and import it to your Eclipse. And by the way… Git rocks!

I almost forgot. Unfortunately Eclipse has a bug in the code formatter. If you use my style and you have a method or constructor that contain only comment(s), the formatter will give a result:

public Thread() {
// TODO Auto-generated constructor stub
}

Which should be:

public Thread() {
    // TODO Auto-generated constructor stub
}

I’ve reported this and you can also use the patch I provided there.

Please let me know if you have special style that I might be interested in!

Java Tips: Iterate and cast

… (or More on cast away with Java generics)

Question: How many times did you encounter this kind of code?

List<Element> l = ...;
for (Element e : l) {
   if (e instanceof SubElement) {
      SubElement se = (SubElement) element;
      // do something
   }
}

If you get that so often, what do you think about this code?

List<Element> l = ...;
for (SubElement se : filter(l)) {
   // do something
}

Nice, huh?

I came across this idea after reading an article Cast away with Java generics. The article suggests a nice approach to cast.

    @SuppressWarnings("unchecked") public static <X> X cast(Object o) {
        return (X) o;
    }

And then you can use it to change an ugly code of:

Session webappSession;
        Map<String, Map<String, Collection<Entity>>> myUglyMap = (Map<String, Map<String, Collection<Entity>>>) (webappSession
                .getAttribute("myUglyMap"));

to a slightly better code:

Session webappSession;
        Map<String, Map<String, Collection<Entity>>> beautiful = cast(webappSession.getAttribute("beautiful"));

To get the nice iteration like I presented in the beginning of the article, I created two methods that reuse this cast method. Here they are:

   public static <X, T extends X> Iterable<T> filter(final Iterable<X> iterable) {
        return new Iterable<T>() {
            @Override public Iterator<T> iterator() {
                return new Iterator<T>() {

                    private T t = null;

                    @Override public boolean hasNext() {
                        while (iterable.iterator().hasNext()) {
                            try {
                                t = cast(iterable.iterator().next());
                                return true;
                            } catch (ClassCastException e) {}
                        }

                        return false;
                    }

                    @Override public T next() {
                        if (t == null) {
                            while (iterable.iterator().hasNext()) {
                                try {
                                    return cast(iterable.iterator().next());
                                } catch (ClassCastException e) {}
                            }
                        }

                        return t;
                    }

                    @Override public void remove() {
                        iterable.iterator().remove();
                    }
                };
            }
        };
    }

    public static <X, T extends X> Iterable<T> filter(final X[] iterable) {
        return new Iterable<T>() {

            @Override public Iterator<T> iterator() {
                return new Iterator<T>() {

                    private int index = 0;

                    @Override public boolean hasNext() {
                        while (index < iterable.length) {
                            try {
                                @SuppressWarnings("unused")
                                T element = cast(iterable[index]);
                                return true;
                            } catch (ClassCastException e) {}
                            index++;
                        }
                        return false;
                    }

                    @Override public T next() {
                        while (index < iterable.length) {
                            try {
                                return cast(iterable[index++]);
                            } catch (ClassCastException e) {}
                            index++;
                        }
                        return null;
                    }

                    @Override public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };

            }

        };
    }

The down side is of course you may have problem with performance because of ClassCastException. But I haven’t profiled it… yet.

Be extremely careful when you initialize a non-final field in the declaration!

Field initialization is one of the basic knowledge every programmer should know. But do you really know all about them? Let me tease you with two trivia questions:

What is the expected printed value for this code?

public class Test {

	private String s = null;

	public Test() {
		init();
	}

	public void init() {
		s = "Halo";
	}

	public String getS() {
		return s;
	}

	public static void main(String[] args) {
		System.out.println(new Test().getS());
	}

}

What is your answer? “Halo”? That’s correct! Congratulation.

Now the second question, I create a parent class for that Test class as follow:

public class Test2 {

	public Test2() {
		init();
	}

	public void init() {
	}

}

Now I modify the Test class a bit to make it fits to the design.

public class Test extends Test2 {

	private String s = null;

	public void init() {
		s = "Halo";
	}

	public String getS() {
		return s;
	}

	public static void main(String[] args) {
		System.out.println(new Test().getS());
	}

}

Now please guess what is the printed value? Still “Halo”? Are you sure?
The correct answer is now it prints null.

Confused?

The problem with second example is the field initialization in class Test is done after the ‘init’ method is called.

I honestly haven’t try to take a look at the reason behind this. According to my logic, this is clearly wrong and Sun should fix this but if anyone can point me to a resource that discuss this, I’d be really glad.

Tip-tip debugging dengan Eclipse (II): Inspeksi (1)

Artikel ini adalah lanjutan artikel terdahulu: Tip-tip debugging dengan Eclipse (I): Breakpoint

Setelah menentukan breakpoint dalam program yang akan didebug, langkah selanjutnya adalah melakukan inspeksi terhadap behavior program. Untuk memulainya, jalankan program dalam modus debug.

Pada gambar diatas, modus debug bisa diaktifkan dengan menekan tombol bergambar (oh well) bug/kutu. Jangan salah tekan dengan tombol yang sebelahnya (mode running) karena pada modus ini semua breakpoint akan diabaikan.

Bila semua berjalan sebagaimana mestinya, aplikasi akan berjalan dan kemudian berhenti di breakpoint. Tugas dalam debugging dimulai disini. Umumnya tugas dalam debugging bisa dibagi menjadi 2 bagian:

  1. Menganalisa jalannya program, dalam hal ini mengecek apakah program memasuki cabang yang diinginkan, misalnya apakah program masuk ke jalur ‘if’ atau ‘else’.
  2. Menganalisa memori (nilai variabel, field, dsb), dalam hal ini mencek apakah nilai dari variabel-variabel tersebut sudah sesuai yang kita inginkan atau belum.

Umumnya kesalahan pada satu bagian menjadi penyebab dari kesalahan di bagian yang lain. Contoh: kesalahan nilai variabel bisa menyebabkan branch tertentu tidak tereksekusi atau kesalahan jalur program menyebabkan nilai variabel menjadi salah.

Harus selalu diingat oleh para pemburu bug: temukan penyebab utama dari bug sebelum memperbaiki bug. Seringkali kita menemukan kesalahan di satu bagian dari aplikasi lalu terburu-buru memperbaikinya padahal kesalahan itu bukanlah penyebab utama dari bug. Hal ini hanya akan memperburuk kondisi aplikasi. Aplikasi menjadi penuh dengan percabangan-percabangan yang tidak jelas dan sebenarnya dapat dihindari.