views:

213

answers:

3

Hi

As per java, instance method resolution is based on runtime types of the arguments.

But while resolving instance variable it uses different approach as shown below.

Output of program is ..

Child
Parent
ParentNonStatic

Here First output is based on runtime types of the argument but third output is not.

can any one explain about this ?

  public class Child extends Parent {

        public static String foo = "Child";
        public String hoo = "ChildNonStatic";

        private Child() {
            super(1);
        }

        @Override
        String please() {
            return "Child";
        }

        public static void main(String[] args) {
            Parent p = new Parent();
            Child c = new Child();

           //Resolving method
            System.out.println(((Parent) c).please());

           //Resolving Static Variable
            System.out.println(((Parent) c).foo);

           //Resolving Instance Variable
            System.out.println(((Parent) c).hoo);
        }
    }
class Parent {

    public static String foo = "Parent";
    public String hoo = "ParentNonStatic";

    public Parent(int a) {
    }

    public Parent() {
    }

    String please() {
        return "Tree";
    }
}
A: 

Fields aren't overridden in the same way methods are. By casting c to Parent, you're indicating that ".hoo" refers to the "hoo" field on Parent, not the one on Child. (To put it in a more technically correct way, field access isn't polymorphic.)

kprevas
+4  A: 

When you upcast an object, you don't actually change the content of the item you are referring to, just the way you treat it. So when you upcast c to parent and call please(), you invoke please() on a Parent, but the dynamic type is still a child, so what really gets invoked is the overridden version in child and "Child" is printed.

When you upcast c and refer to foo, you are not making a function call. The compiler can determine at compile time what you are referring to. In this case, the field foo of an object that has the type parent. Fields and static fields are not overridden. Instead, they are hidden. What you actually end up doing with this upcast is helping Java pick the hidden version (the one from Parent) rather than the one from child. Similarly, with hoo you get the version of the parent.

Here's some info from the JAva tutorial: http://java.sun.com/docs/books/tutorial/java/IandI/hidevariables.html

Uri
+1  A: 

In Java you don't actually "cast". Java doesn't actually do anything when you ask for a cast except to check if the object can be cast to that type thus why casts can throw a "ClassCastException".

The compiler though understands casts and thus uses them to validate that method calls are appropriate.

With respect to static fields, the compiler in fact removes any instance variables and references the field via the class according whatever the return type is.

Parent p = new Parent();
Child c = new Child(); 
Parent pc = new Child();

System.out.println(c.foo); // will print Child
System.out.println(p.foo); // will print Parent
System.out.println(pc.foo); // will print Parent
System.out.println(((Child)pc).foo) // will print Child

Fields seem to work the same way.

I think in a nutshell that java does dynamic binding on methods and static binding on fields.

Michael Wiles