Results 1 to 10 of 10

Thread: SCJP Exam Question

  1. #1

    Thread Starter
    Dazed Member
    Join Date
    Oct 1999
    Location
    Ridgefield Park, NJ
    Posts
    3,418

    SCJP Exam Question

    Code:
    public class MyClass{
      public static void main(String[] args){
        MyClass a;
        MySubclass b; 
     
        a = new MyClass(); 
        b = new MySubclass(); 
     
        a = b; 
        b = a; // fails 
        
        a = new MySubclass(); 
        b = new MyClass(); 
      }
     }
    
     class MySubclass extends MyClass{}
    Im wondering why the line marked // fails causes the program not to compile. b = a now a can reference MySubclass. b = a MySubclass back into
    MySubClass reference.

  2. #2
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    A base class reference can reference a derived class, but not vice versa.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  3. #3

    Thread Starter
    Dazed Member
    Join Date
    Oct 1999
    Location
    Ridgefield Park, NJ
    Posts
    3,418
    Posted by CornedBee

    A base class reference can reference a derived class, but not vice versa.
    Yes i understand that.

    I think i am misinterpreting the assignments. In a = b what is actually going on? I know it's a widening conversion or upcast whatever you want to call it but is seems that in this line ie.. a = b references seem to stay the same because b = a, a is still the supertype and b is still the sub type where the assignment is illegal because as you said a derived class cannot refrence a base class.

  4. #4
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Here's the main function again, with places marked for comments.
    Code:
      public static void main(String[] args){
        // Pos 1
        MyClass a;
        MySubclass b; 
        // Pos 2
        a = new MyClass(); 
        b = new MySubclass(); 
        // Pos 3
        a = b;
        // Pos 4
        b = a; // fails 
        // Pos 5
        a = new MySubclass(); 
        // Pos 6
        b = new MyClass(); // fails
        // Pos 7
      }
    At pos 1, there are no objects, simple enough.
    At pos 2, there are two references. a is a reference to a MyClass, b is a reference to a MySubclass, which derives from MyClass. Both references point to nothing.
    At pos 3, a points to an object of type MyClass on the heap, let's call it W. b points to an object of type MySubclass on the heap, called X. This is no problem, because a is a ref to MyClass and b to MySubclass.
    At pos 4, a has been assigned the value of b. This means that both a and b now point to X, W has been abandoned and will eventually be garbage collected. a can point to X because MySubclass is a subclass of MyClass. The downcast on the reference is performed automatically. This has absolutely no effect on X itself, though.
    At pos 5, it has been attempted to assign the value of a back to b. However, a is a ref to MyClass, b to MySubclass. An upcast cannot be performed implicitely, you must explicitely cast it:
    b = (MySubclass)a;
    This delays the type check from compile time, where only the reference types are used, to runtime, where the actual object types are used. If you remove the a=b line now, this line will throw a InvalidCastException (or is it ClassCastException?).
    Anyway, at pos 6, a new object Y of type MySubclass has been assigned to a, which is again possible because of the implicit downcast.
    The last line again fails to compile, because new MyClass produces a reference of type MyClass, which needs a cast to be assigned to a reference of type MySubclass. This time, however, the cast is doomed to fail, because the underlying object Z is simply a MyClass, not a MySubclass.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  5. #5

    Thread Starter
    Dazed Member
    Join Date
    Oct 1999
    Location
    Ridgefield Park, NJ
    Posts
    3,418
    Posted by CornedBee

    At pos 4, a has been assigned the value of b.
    This means that both a and b now point to X,
    W has been abandoned and will eventually be garbage collected.
    a can point to X because MySubclass is a subclass of MyClass.
    The downcast on the reference is performed automatically.
    This has absolutely no effect on X itself, though.
    What i don't understand is why the downcast is implicit. When assigning smaller type to a larger type the cast is always implicit. Visa versa cast mandatory.

    Posted by CornedBee

    At pos 5, it has been attempted to assign the value of a back to b.
    However, a is a ref to MyClass, b to MySubclass. An upcast cannot be performed implicitely, you must explicitely cast it:
    b = (MySubclass)a;
    Now you said that both a and b now point to x(which is MySubclass) so
    why would the assignment b = a fail? You are just storing a which now
    references MySubclass(from the previous a = b assignment)
    into b which still references MySubclass. Plus
    also in the second quote i think you mean a downcast cannot be performed implicitely.

    Ill have to wait till i get home to take a good look at all of this
    right now im at work and i keep having to get up every five seconds. Thanks for replying.

  6. #6
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    I thought this was a widening conversion.
    The terms widening and narrowing conversions only apply to primitives.

    Now you said that both a and b now point to x(which is MySubclass) so
    why would the assignment b = a fail?
    It fails at compile-time, because the compiler doesn't know that a really points to a MySubclass. The assignment is insecure, which is why the explicit cast is required.

    also in the second quote i think you mean a downcast cannot be performed implicitely.
    Maybe. I use downcast to mean from derived class to base class and upcast to mean from base class to derived class. Using this definition, my quote is correct.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  7. #7

    Thread Starter
    Dazed Member
    Join Date
    Oct 1999
    Location
    Ridgefield Park, NJ
    Posts
    3,418
    Posted by CornedBee

    The terms widening and narrowing conversions only apply to primitives.
    Yeah sorry i have a bad habbit of using widening and narrowing to loosely.

    Posted by CornedBee

    It fails at compile-time, because the compiler doesn't know that a really points to a MySubclass. The assignment is insecure, which is why the explicit cast is required.
    This is one thing that i have never understood. Why would the compiler not be able to determine what object a variable references?

  8. #8
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Because at compile-time it doesn't reference anything. Here's an example:
    Code:
    class Base {}
    class A extends Base {}
    class B extends Base {}
    class C extends Base {}
    
    public class Core {
      public static void main(String[] args) {
        int i = (int)(Math.random()*3.0);
        Base b;
        switch(i) {
          case 0:
            b = new A();
            break;
    
          case 1:
            b = new B();
            break;
    
          case 2:
            b = new C();
            break;
        }
        A a = b; // !!!
      }
    }
    How would the compiler know whether the marked assignment is valid? If i is 0 then it is, otherwise it isn't.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

  9. #9

    Thread Starter
    Dazed Member
    Join Date
    Oct 1999
    Location
    Ridgefield Park, NJ
    Posts
    3,418
    Posted by CornedBee
    Because at compile-time it doesn't reference anything.
    Neither does a = b. But it's still allowed at compile time.
    Code:
    public class MyClass{
      public static void main(String[] args){
          MyClass a;
          MySubclass b; 
     
          a = new MyClass(); 
          b = new MySubclass(); 
     
          a = b; // allowed  
          b = a; // fails   
         }
       }
    class MySubclass extends MyClass{}
    Posted by CornedBee

    How would the compiler know whether the marked assignment is valid? If i is 0 then it is, otherwise it isn't.
    Under the context of the code you provided of course the compiler would not be able to determine if the assignment is valid. Under the above code there is no ambiguity(not at least the way i look at it)

  10. #10
    Kitten CornedBee's Avatar
    Join Date
    Aug 2001
    Location
    In a microchip!
    Posts
    11,594
    Neither does a = b. But it's still allowed at compile time.
    Because it's safe. Whatever b references, a can reference too, that much is guaranteed. But not all that a can reference can be referenced by b, that's why it's an unsafe cast and requires the explicit cast.

    Under the context of the code you provided of course the compiler would not be able to determine if the assignment is valid. Under the above code there is no ambiguity(not at least the way i look at it)
    Indeed not, but your code is unrealistic. 90% of the cases, the compiler won't be able to determine the true type at compile-time, which is why it doesn't even try in the first place.
    All the buzzt
    CornedBee

    "Writing specifications is like writing a novel. Writing code is like writing poetry."
    - Anonymous, published by Raymond Chen

    Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width