|
-
Jul 25th, 2004, 01:23 PM
#1
Thread Starter
Dazed Member
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.
-
Jul 25th, 2004, 03:52 PM
#2
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.
-
Jul 25th, 2004, 04:42 PM
#3
Thread Starter
Dazed Member
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.
-
Jul 26th, 2004, 02:56 AM
#4
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.
-
Jul 27th, 2004, 03:02 PM
#5
Thread Starter
Dazed Member
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.
Last edited by Dilenger4; Jul 27th, 2004 at 06:23 PM.
-
Jul 27th, 2004, 03:12 PM
#6
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.
-
Jul 27th, 2004, 06:18 PM
#7
Thread Starter
Dazed Member
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?
-
Jul 28th, 2004, 03:58 AM
#8
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.
-
Jul 28th, 2004, 05:56 PM
#9
Thread Starter
Dazed Member
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)
-
Jul 29th, 2004, 01:35 AM
#10
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|