The terms "upcasting" and "downcasting" are C++ terms, not
Java terms. They do not occur in the JLS. But having said that, I have to add that if they were used in Java, then you would be using them right (:-). That is, your understanding seems to be approximately correct.
You further asked somewhere about whether they could be considered widening/narrowing conversions. The answer is yes: the conversions that you are calling upcasting/downcasting are described in the JLS as widening/narrowing conversions.
Here is the citation:
5.5 Casting Conversion
... Casting contexts allow the use of an identity conversion (�5.1.1), a widening primitive conversion (�5.1.2), a narrowing primitive conversion (�5.1.3), a widening reference conversion (�5.1.4) [this is your upcasting], or a narrowing reference conversion (�5.1.5) [your downcasting].
A bit later you wrote the following about what you call upcasting:
"A subclass ref. is assigned to a superclass reference this makes the subclass object can be used where the superclass can be used.
Thus a subclass is replacing a superclass object. "
You are headed in the right direction, but I have some problems with putting it this way.
Say that Boat is a subclass of Vehicle, and we write:
Vehicle v;
Boat b = new Boat();
v = b;
Now in the assignment "v = b", nothing is being replaced. (Of course the old value of v is being replaced with a new one but I don't think that's what you were referring to.)
What is happening is that a **value** is being put into a kind of value-container called a **variable**. We know (at compile time) that the value, at runtime, will certainly be an instance of Boat, or some subclass of Boat, perhaps a Dory. And we declared V as a Vehicle, which means you can put a reference to any vehicle into it. Since Boat is a subclass of Vehicle, anything that is a Boat is also a Vehicle, so this is legal.
But there is nothing being replaced and nothing being changed, except which vehicle v currently points at.
So much for upcasting; now let's consider downcasting, with the same class hierarchy but the code:
Boat b;
Vehicle v;
<code which sets v to something legal>
b = (Boat)v;
Here we defined a variable b that can hold any value that is an instance of a Boat. We assign to it the current value of v. The compiler knows that the value of v must be a vehicle but not every vehicle is a boat. so you have to say, explicitly, that you intend to do this, and accept the risk of a runtime error if the value of v turns out to be, say, a wheelbarrow.
Again, nothing is replaced (except the old value of b) and nothing is changed. The object itself does not change its type. It just goes into a different location, where a different amount of knowledge is known at compile time, but the real reality is runtime, and this particular value (let's say it's the Dory "Hattie S"), is always the same thing, and the same type, wherever it gets put.
[This message has been edited by Jim Goodwin (edited September 15, 2000).]
[This message has been edited by Jim Goodwin (edited September 15, 2000).]