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

Express killers, part V

Damian Szczepanik

Issue 6 (2009-12-09)

First example

Today we will start from short code for perceptive. Question is: Assuming that following class compiles and it throws exception during runtime, what is the class name of obj?

    public class ClassType {
        // obj type definition

        public static void main(String[] args) {
            Object pattern = ClassType.class;
            for (int i = 0; i < obj.length(); i++) {
                if (pattern.equals(obj))
                    obj += 5;
                else
                    obj += -5;
                System.err.println(obj);
            }
        }
    }

If it is too hard, copy it to your IDE. It will help you find the solution.

Second example

In the second part (this time without IDE help) focus on problems with encapsulation and overwriting properties. What will be result of execution following main() method?

    public class AccessingToOverridenAttribute {
        public int a;

        public void add() {
            a = 10;
        }

        public static void main(String[] args) {
            AccessingToOverridenAttribute f = new Bar();
            f.add();
            System.err.println(++f.a);
            System.err.println(++((Bar) f).a);
        }
    }


    class Bar extends AccessingToOverridenAttribute {
        public int a = 2;

        public void add() {
            a = 5;
        }
    }

Solutions:

First example:

Key to solve this puzzle is length() method and add operation. First, obj can't be a table beause in the for loop method length() is used, not length property. It means that obj is a reference to the object that implements length() method. None of the primitive type wrapper (like Integer or Double) implements this method. However, String does. Is it possible that obj is type of any other class that user implements? Length() method will not be a problem in this case, because you can implement it. However add operator would be a problem. It is only allowed for primitive types, its wrappers and String class. Java doesn't allow operator overloading (as it is in C++). String is also immutable class, so you can't extend it. Gathering it all together, the only possibility is that obj is a type of String class. In addition, it can't be null as it will throw exception during the runtime.

Second example:

Fist, add() method will be executed based on real type of object f, not the type declaration. So the control will go to Bar class. It means that value of a property of the base class will not be changed.

Second, f.a execution will result in printing property based on the declared variable type, not the real object type. It will be defined in the compilation phase and it doesn't matter, that derived class declares property with the same name. It is bad practice to name the property the same as in the base class and you shouldn't allow access to this property that will allow using the construction we presented in this example.

Third, printing property by ((Bar) f).a will follow the rule we have just explained. Compiler in the compilation phase will choose property of the derived class, because of the explicit casting.

Summary: Properties shouldn't be visible outside of the class scope and should be accessed by getters and setters. It will eliminate the problems we have just presented and allow easier debugging.

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