12

I have the following code.

class Test {
    int i = 0;

    Test() {
        System.out.println(this);
        System.out.println(this.i);
    }

}

public class Demo extends Test {
    int i = 10;

    Demo() {
        super();
        System.out.println("calling super");
        System.out.println(this);
        System.out.println(this.i);    
    }

    public static void main(String[] args) throws IOException {    
        Demo d = new Demo();    
    }
}

O/P : Demo@2e6e1408
0
calling super
Demo@2e6e1408
10

When I execute the program and print the value of "this", in both super class constructor as well as in child class constructor, the value of this (address location) is displayed as childClassName@someValue .. My question is, why dont I get the value of Test i.e, Test@someVal (Super class) when I print value of "this" in the super class.. ASAIK, Super class will also have a place/location in memory, so, why am I not getting Test@someValue in the first SOP...

PS : I know variables are referenced based on the reference type (LHS) and methods are called based on the object type (RHS)..

4J41
  • 5,005
  • 1
  • 29
  • 41
TheLostMind
  • 35,966
  • 12
  • 68
  • 104
  • Your recent edit seems to be trying to change the question to something else. The simple answer is that class `Test` hasn't got a function called `somFunc` so it has a compile failure. `Demo` on the other hand has that function so it will compile. This is pretty basic inheritance stuff and if you don't understand that you probably want to go read some stuff on it. – Chris Dec 30 '13 at 11:59
  • @Chris - I started off asking something, ended up asking something else.. removed the edit :P – TheLostMind Dec 30 '13 at 12:01
  • Yup. Its easy enough to do but can confuse people (like me) who come and look at the answers after the question has changed. :) Do feel free to ask the question as a new question though if you are having trouble with it still. – Chris Dec 30 '13 at 12:20

2 Answers2

10

When I execute the program and print the value of "this", in both super class constructor as well as in child class constructor, the value of this (address location)...

The output of System.out.println(this) with the default Object#toString is not the address of the instance in memory. It's just the name of the class and the instance's hash code, nothing more. From the documentation:

The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

getClass().getName() + '@' + Integer.toHexString(hashCode())

It's true that the hashCode documentation says

This is typically implemented by converting the internal address of the object into an integer...

but it also says

...but this implementation technique is not required by the JavaTM programming language.

...and of course the JVM is free to move instances around in memory as necessary, but isn't allowed to change the hashCode.


...why dont I get the value of Test i.e, Test@someVal (Super class) when I print value of "this" in the super class.

There is one instance. That instance is of the subclass. When you do System.out.println(this), it doesn't matter whether you do that in the base class or the subclass, it's still the same object instance you're using. That one object has features it gets from the subclass and also features it inherits from the superclass, but there aren't two separate instances; there's one instance with a combined set of features. super isn't an object reference, although it looks a bit like one; it's a syntax mechanism for specifically asking the compiler to use a feature the instance inherits from the superclass rather than the equivalent feature of the instance (in case they're different).

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • ok... getClass().getName() + '@' + Integer.toHexString(hashCode()) ... this should refer to the current object in the Test class right??.. I mean is it correct to use "the child object" as the current object even in the parent class ?. The parent object will have its own hashcode and name. Why not use it?? – TheLostMind Dec 30 '13 at 06:53
  • @TheLostMind: There is no "parent object." There is **one** object, which has features it receives from the subclass and also from the superclass. This is the fundamental point: There are not two separate objects. There are languages that do inheritance that way, which is called *prototypical inheritance* (JavaScript is one of those, for instance), but Java isn't one of them. Java does *classical inheritance*. – T.J. Crowder Dec 30 '13 at 06:56
  • Then how will the JVM differentiate b/w the variables "i" in Demo and Test classes.. I a using "this" on both occassions, then I must be getting the same result... – TheLostMind Dec 30 '13 at 06:58
  • @TheLostMind: The JVM does bookkeeping to keep track of which `i` you're talking about. You can think of it as the one object has a private member called `Test$i` and another one called `Demo$i`. The compiler figures out which of those to use based on the type of the reference you use when accessing it. If the reference has the type `Demo`, it uses `Demo$i`; if it has the type `Test`, it uses `Test$i`. The *type* of `this` is based on the code in which it's written (e.g., it's `Demo` in `Demo` and `Test` in `Test`), even though the *value* of `this` is the same in both cases. – T.J. Crowder Dec 30 '13 at 07:01
  • @TheLostMind: You can see the effect the type of the reference has by adding these lines to your `Demo` output: `Test t = this; System.out.println(t.i);` Since we access `i` via `t`, which is of type `Test`, we get `Test`'s version of `i` (`0`). – T.J. Crowder Dec 30 '13 at 07:05
  • Thanks :) .. Please see my edit.. Why cant I call someFunc() from "this" in superclass while i can call it from subClass ??. If "this" refers to "combined object", it should allow me to call right? – TheLostMind Dec 30 '13 at 07:06
  • @TheLostMind: Because of the *type* of the reference. Again: In `Test`, `this` is of type `Test` (even though it refers to a `Demo` object). `Test` doesn't have `someFunc`, so you can't call it. In classical inheritance, one of the fundamental concepts is that the type of reference you have controls what aspects of an object you're allowed to use. It's the same principal that says if you have a `Map` reference to a `HashMap`, you can't use anything from `HashMap` that isn't defined for `Map`. – T.J. Crowder Dec 30 '13 at 07:07
  • But only fields are accessed via references... and methods are accessed via objects... right? – TheLostMind Dec 30 '13 at 07:08
  • 1
    @TheLostMind: Wrong, I'm afraid. :-) Fields and methods are both accessed via references. I have to get back to work, I suggest continuing to work through tutorials and reading on the subject, you'll get there. But the main take-aways here are: 1. There is **one** object. 2. The type of reference you have to the object controls what you can see, and which version of something (the `i` member) you see. – T.J. Crowder Dec 30 '13 at 07:10
2

Demo is a composition of 3 classes: itself, Test and Object. But an instance of Demo is one object, in memory it consists of fields of its super class + its own fields: Test.i + Demo.i (Object has no fields).

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • So you mean to say that.. Both Demo as well as Test are combined into one object in memory?.. – TheLostMind Dec 30 '13 at 06:55
  • absolutely, and this is why "this" is the same whatever Demo@2e6e1408 means – Evgeniy Dorofeev Dec 30 '13 at 06:59
  • Then how will the JVM differentiate b/w the variables "i" in Demo and Test classes.. I a using "this" on both occassions, then I must be getting the same result. – TheLostMind Dec 30 '13 at 07:00
  • JVM knows that this.i inside Test is Test.i. If you want to print Demo.i from Test do it this way Demo.this.i – Evgeniy Dorofeev Dec 30 '13 at 07:03
  • Thanks :) .. Please see my edit.. Why cant I call someFunc() from this in superclass while i can call it from subClass ??. If "this" refers to "combinedobject", it should allow me to call right? – TheLostMind Dec 30 '13 at 07:07
  • because non static / non private methods are virtual, if a method is overridden in subclass when you call it inside super JVM redirects it to subclass method – Evgeniy Dorofeev Dec 30 '13 at 07:14
  • why can't JVM automatically detect that its demoObject.someFunc() and redirect?? – TheLostMind Dec 30 '13 at 07:15
  • this is exactly what it does - automatically detects the write one. Test.someFunc() is a real code, it stays with the class when loaded (only fields merge in subclass) so there are 2 implementions but JVM makes virtual call which assumes checking for actual type. Try to make it static and you will see difference – Evgeniy Dorofeev Dec 30 '13 at 07:21