Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #8748 > unrolled thread

Java casting question

Started byChad <cdalten@gmail.com>
First post2011-10-12 18:27 -0700
Last post2011-10-12 23:40 -0700
Articles 6 — 5 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Java casting question Chad <cdalten@gmail.com> - 2011-10-12 18:27 -0700
    Re: Java casting question Arne Vajhøj <arne@vajhoej.dk> - 2011-10-12 21:36 -0400
      Re: Java casting question Lew <lewbloch@gmail.com> - 2011-10-12 19:05 -0700
        Re: Java casting question Andreas Leitgeb <avl@gamma.logic.tuwien.ac.at> - 2011-10-13 10:24 +0000
        Re: Java casting question Arne Vajhøj <arne@vajhoej.dk> - 2011-11-06 17:08 -0500
    Re: Java casting question Travers Naran <tnaran@gmail.com> - 2011-10-12 23:40 -0700

#8748 — Java casting question

FromChad <cdalten@gmail.com>
Date2011-10-12 18:27 -0700
SubjectJava casting question
Message-ID<c6d9d3ed-7892-40e0-ac9a-abb957b93241@e9g2000prg.googlegroups.com>
Given the following...

class X {
    void f1() { System.out.println("XXX");}
    void f2() { System.out.println("AAA"); f1();}
}

class Y extends X {
    void f1() { System.out.println("YYY"); }
}

class Z extends X {
    void f1() { System.out.println("ZZZ"); }
}
public class Main {

    static void g(X a) {
        a.f2();
    }
    public static void main(String[] args) {
        X x = new X();
        Y y = new Y();
        Z z = new Z();

        Object obj = new Y();
        ((X) obj).f2();
        g(z);
        //y = (Y)x;
    }

}

I get the following output..

AAA
YYY
AAA
ZZZ


The question is about

Object obj = new Y();
((X) obj).f2();


How come YYY, but not XXX, gets printed on the second line? Both f1()
and f2() are in class X. So shouldn't f1() also have been casted to
(type) X?

Chad

[toc] | [next] | [standalone]


#8749

FromArne Vajhøj <arne@vajhoej.dk>
Date2011-10-12 21:36 -0400
Message-ID<4e964097$0$281$14726298@news.sunsite.dk>
In reply to#8748
On 10/12/2011 9:27 PM, Chad wrote:
> Given the following...
>
> class X {
>      void f1() { System.out.println("XXX");}
>      void f2() { System.out.println("AAA"); f1();}
> }
>
> class Y extends X {
>      void f1() { System.out.println("YYY"); }
> }
>
> class Z extends X {
>      void f1() { System.out.println("ZZZ"); }
> }
> public class Main {
>
>      static void g(X a) {
>          a.f2();
>      }
>      public static void main(String[] args) {
>          X x = new X();
>          Y y = new Y();
>          Z z = new Z();
>
>          Object obj = new Y();
>          ((X) obj).f2();
>          g(z);
>          //y = (Y)x;
>      }
>
> }
>
> I get the following output..
>
> AAA
> YYY
> AAA
> ZZZ
>
>
> The question is about
>
> Object obj = new Y();
> ((X) obj).f2();
>
>
> How come YYY, but not XXX, gets printed on the second line? Both f1()
> and f2() are in class X. So shouldn't f1() also have been casted to
> (type) X?

((X) obj).f2();

and

((Y) obj).f2();

should give the same output.

Virtual methods are stored in the object and it really
does not matter what type the ref is declared to.

Arne

[toc] | [prev] | [next] | [standalone]


#8750

FromLew <lewbloch@gmail.com>
Date2011-10-12 19:05 -0700
Message-ID<4447573.399.1318471540216.JavaMail.geo-discussion-forums@prfp13>
In reply to#8749
Arne Vajhøj wrote:
> Chad wrote:
>> Given the following...
>>
>> class X {
>>      void f1() { System.out.println("XXX");}
>>      void f2() { System.out.println("AAA"); f1();}
>> }
>>
>> class Y extends X {
>>      void f1() { System.out.println("YYY"); }
>> }
>>
>> class Z extends X {
>>      void f1() { System.out.println("ZZZ"); }
>> }
>> public class Main {
>>
>>      static void g(X a) {
>>          a.f2();
>>      }
>>      public static void main(String[] args) {
>>          X x = new X();
>>          Y y = new Y();
>>          Z z = new Z();
>>
>>          Object obj = new Y();
>>          ((X) obj).f2();
>>          g(z);
>>          //y = (Y)x;
>>      }
>>
>> }
>>
>> I get the following output..
>>
>> AAA
>> YYY
>> AAA
>> ZZZ
>>
>>
>> The question is about
>>
>> Object obj = new Y();
>> ((X) obj).f2();
>>
>>
>> How come YYY, but not XXX, gets printed on the second line? Both f1()
>> and f2() are in class X. So shouldn't f1() also have been casted [sic] to
>> (type) X?

The past participle of "to cast" is "cast", not "casted".

Casting from a type to a supertype is automatic, so the '(X)' cast in your code is superfluous.  Since 'Y' /is-an/ 'X',. your 'obj' of type 'Y' is already of type 'X'; no cast needed.  (In Java, casting to a parent type is "upcasting" or "widening", and comes for free.  Casting to an extending type is "downcasting" or "narrowing", and requires a cast operator.)

And no, you should not see the 'X' version of the output from your 'Y' instance, for the reason Arne explained:
> ((X) obj).f2(); 
> 
> and
> 
> ((Y) obj).f2();
> 
> should give the same output.
> 
> Virtual methods are stored in the object and it really
> does not matter what type the ref is declared to.

To put it another way, the object instance "knows" its own type.  You cannot call a method on the supertype that exists only in the subtype, but if you call a method that exists in the supertype that the instance's subtype overrides, you will get the overridden version.

This is a key to how object-oriented programming works.

Instances own their own members (methods and variables); the declared type only controls what the compiler is allowed to see, not how the method behaves.

Arne referred to "virtual methods".  That means the method call is dispatched to the instance, not literally called from the reference.  The instance uses its own version of the method - the parent type's if not overridden, the derived type's if it is overridden.

Read the Java Language Specification (JLS) for the gory details.

-- 
Lew

[toc] | [prev] | [next] | [standalone]


#8756

FromAndreas Leitgeb <avl@gamma.logic.tuwien.ac.at>
Date2011-10-13 10:24 +0000
Message-ID<slrnj9df30.6gl.avl@gamma.logic.tuwien.ac.at>
In reply to#8750
Lew <lewbloch@gmail.com> wrote:
> To put it another way, the object instance "knows" its own type.
> You cannot call a method on the supertype that exists only in the
> subtype, but if you call a method that exists in the supertype that
> the instance's subtype overrides, you will get the overridden version.

At compile-time, the static type determines which method signature is
picked, but at runtime the actual implementation for that signature
is picked based on the object's actual type.

Here is another example:

class Test {
   void f1(Test o) { System.out.println("Test.f1(Test)"); }
}
class SubTest extends Test {
   void f1(Test o) { System.out.println("SubTest.f1(Test)"); }
   void f1(SubTest o) { System.out.println("SubTest.f1(SubTest)"); }
}
public class Main {
   public static void main(String[] args) {
      SubTest   st = new SubTest();

      st          .f1(st);
      ((Test) st) .f1(st);
   }
}

Output:
SubTest.f1(SubTest)
SubTest.f1(Test)

This shows, how the compiler settles on a method:
  for the first call, the compiler sees static type SubTest, and
     from among the two over*loads* picks the one most specifically
     matching the static type of the arguments: f1(SubTest).
  for the second call, the compiler sees static type  Test, and
     Test only has one version f1(Test), so the compiler picks that.
     At runtime, however,  SubTest.f1(Test) is called, as the object
     itself is a SubTest.

> This is a key to how object-oriented programming works.
yup


PS: (for Lew)
Lew <lewbloch@gmail.com> wrote:
>>> Object obj = new Y();
>>> ((X) obj).f2();
> Casting from a type to a supertype is automatic,
> so the '(X)' cast in your code is superfluous.
The premise did not apply, thus neither does the conclusion.

[toc] | [prev] | [next] | [standalone]


#9685

FromArne Vajhøj <arne@vajhoej.dk>
Date2011-11-06 17:08 -0500
Message-ID<4eb7056b$0$288$14726298@news.sunsite.dk>
In reply to#8750
On 10/12/2011 10:05 PM, Lew wrote:
> Arne Vajhøj wrote:
>> ((X) obj).f2();
>>
>> and
>>
>> ((Y) obj).f2();
>>
>> should give the same output.
>>
>> Virtual methods are stored in the object and it really
>> does not matter what type the ref is declared to.
>
> To put it another way, the object instance "knows" its own type.  You cannot call a method on the supertype that exists only in the subtype, but if you call a method that exists in the supertype that the instance's subtype overrides, you will get the overridden version.
>
> This is a key to how object-oriented programming works.
>
> Instances own their own members (methods and variables); the declared type only controls what the compiler is allowed to see, not how the method behaves.

It may be worth noting that even though in Java all (non static)
methods are virtual then there are other OO languages like
C++ and C# where one need to explicit declare them virtual.

Arne

[toc] | [prev] | [next] | [standalone]


#8753

FromTravers Naran <tnaran@gmail.com>
Date2011-10-12 23:40 -0700
Message-ID<j7614l$ehf$1@dont-email.me>
In reply to#8748
On 12/10/2011 6:27 PM, Chad wrote:
> AAA
> YYY
> AAA
> ZZZ
>
>
> The question is about
>
> Object obj = new Y();
> ((X) obj).f2();
>
>
> How come YYY, but not XXX, gets printed on the second line? Both f1()
> and f2() are in class X. So shouldn't f1() also have been casted to
> (type) X?

You're not understanding what casting in Java means, nor how Java 
implements methods.

You seem to be thinking that (X)obj _converts_ obj into an instance of X 
complete with X's methods.  That is incorrect.  Obj will _always_ 
remember it is Y and any method calls on Obj will go to Y's methods 
first.  Casting can _never_ change that.  Ever.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web