JAVA exPress logo Published on JAVA exPress (http://www.javaexpress.pl)

Express killers, part IV

Damian Szczepanik

Issue 5 (2009-10-01)

First, quick reminder: what will be result when you execute following code?

    public class Loader {
        {
            System.out.println("a");
        }

        X x;
        static {
            System.out.println("b");
        }

        Loader() {
            System.out.println("c");
        }

        {
            System.out.println("d");
        }

        static class X {

            static {
                System.out.println("e");
            }
        }

        public static void main(String[] args) {
            System.out.println("f");
            new Loader();
        }
    }

When we get into this piece of code we realized (surprisingly!) that it doesn't compile, but it is simple and fixing doesn't take a lot of time. However, what if we have following restrictions in code manipulation:

What can you do, to make this code able to compile without changing the result?

    class Parent {
    }

    class A extends Parent {
        public boolean test() {
            return false;
        }
    }

    class B extends Parent {
        public boolean test() {
            return true;
        }
    }

    public class X {
        public static void main(String[] args) {
            A a = new A();
            B b = new B();
            boolean t = (true ? a : b).test();
        }
    }

Results:

First example:

Result will be:

b – after class is loaded, static blocks are executed,

f – execution of main() method,

a, d – creation object of class Loader will execute subsequent (ordered by position in class) class initializations blocks,

c – execution of class constructor.

Letter e will not be printed because static inner class is loaded at the time of first usage. In above example this class is not created, so it will not be loaded as well. Even despite the fact, that it is attribute in class Loader, because it is just type declaration and object is not created.

Second example:

Tenary operator can't be used as it is, because compiler:

Compiler at the compile phase can't define what will be the result of the ternary operator (even though in this example, optimizer can figure out resulting type), so we have to be sure that in both cases calling method test() will be possible.

Besides that in this example, both types have test() method, compiler will look for common super class, so it will find Parent class, that doesn't have test() method.

What can we do about it? If ternary operator can't be changed, it means we have to assure that Parent class has test() method. We can do it:

The best solution would be to remove ternary operator and replace it with if-else statement. In this case modification of Parent class will be not needed.

Source: http://www.javaexpress.pl/article/show/Express_killers_part_IV