The words "upcasting" and "downcasting" refer to the manner in which inheritance relationships are typically diagrammed.
Suppose we have a Car class. And suppose that Volkswagen and Volvo both extend Car. Furthermore, Jetta and Beetle both extend Volkswagen. This inheritance relationship is typically diagrammed with the base class at the top and the extending classes underneath.
Now, an instance of Jetta is also an instance of Volkswagen, as well as an instance of Car. So it's perfectly valid to say Volkswagen v = new Jetta(); or Car c = new Jetta(); These are examples of upcasting, because the reference to an instance of Jetta is being cast to a type "above" it.
In contrast, downcasting is casting to a type "below." For example, if we have Car c = new Jetta();, we could then downcast the reference by assigning it to a variable of type Volkswagen. But not all Cars are Volkswagens! And so we need to assure the compiler that this particular instance of Car is, in fact, a Volkswagen. We do this with an "explicit cast," which means we have to explicitly specify the new type in parentheses. For example, Volkswagen v = (Volkswagen)c;. Of course, the object itself is still an instance of Jetta. It's only the reference type that's changing from Car to Volkswagen.
On the other hand, suppose our instance is actually something else, like Car c = new Volvo(); And then we explicitly cast it to type Volkswagen with Volkswagen v = (Volkswagen)c;. In this case, the code would compile because we've told the compiler that this instance of Car is really a Volkswagen -- but the program would throw an exception at runtime because we gave the compiler false information. This instance of Car is a Volvo, and a Volvo is not a Volkswagen.
Note that upcasting is always "safe," so explicit casting is not required for upcasts.