Here also staff[1] is the superclass object which is being typecasted to subclass (Manager) object. So why should it give problem here. I am just typecasting a superclass variable to a subclass object. What's the problem :(

The runtime is telling you what is going wrong: Employee cannot be cast to Manager.

Your code includes something (staff[1]) whose value is a reference to a person called "ABC". Of course, in general staff[1] might be a reference to a Manager or some other subclass of Employee. But not in this case. In this case staff[1] is a reference to a very particular person called "ABC" who is on a salary of 1000 and ... who is not a Manager.

The runtime knows this particular person (Employee instance) is not a Manager and so you get an error.

The compiler is not going to stop you doing this cast - as noted above staff[1] might have a reference value that points to a Manager. Casting staff[1] to Manager is, in general, a reasonable thing to do. But at runtime the actual instance being pointed to either is a Manager or it isn't. And if it isn't you'll get an error.

Here also staff[1] is the superclass object which is being typecasted to subclass (Manager) object.

Actually staff1 is an expression not an object. You can cast variables and the results of expressions - but this won't alter their value. A cast won't turn an Employee into a Manager. Rather it lets you take something that is a reference to an Employee and use it as if it were a reference to a Manager.

Maybe the following (paste it into the main method) will make it a little clearer. test2 is the case that is giving you grief.

Employee emp = new Employee("ABC", 1000);
Employee man = new Manager("XYZ", 2000);
String str = "foo";
// compiler says OK, because man (the variable) is an employee
// reference and they can be manager references
// ---
// runtime says OK, because man (the instance) is, in fact, a manager
Manager test1 = (Manager)man;
// compiler says OK, because emp (the variable) is an employee
// reference and they can be manager references
// ---
// runtime says ERROR!, because emp (the instance) is, in fact,
// NOT a manager
Manager test2 = (Manager)emp;
// compiler says MESSAGE! and won't compile, because str (the variable) is
// a string reference and they can never be manager references
// ---
// runtime never gets to say anything
Manager test3 = (Manager)str;

I've added 8 lines to the bottom of the main() method. (To see what the last 4 do you will have to first comment out the 4 lines before them.)

// o is a variable whose value can be any reference to an Object.
// It is assigned a reference to an A1
// ---
// What is o: a reference to an Object, or a reference to an A1?
// It's both! It has the type "reference to Object", but its value
// which can change from time to time, is currently a reference to
// an A1
Object o = new A1();
// abc is a variable whose value can be any reference to an A1.
// It is assigned the same reference that o has.
// ---
// The compiler is OK with the cast because Object is a super class
// of A1. The runtime will have no problems with it either because
// the thing being referenced really is an A1 - after all, it was
// created with new A1()
A1 abc = (A1)o;
// Very similar to the first two statements. And both the compiler
// and runtime will be happy for exactly the same reasons.
A1 a1 = new B1();
B1 ab = (B1)a1;
ab.amethod();
ab.bmethod();
// This looks like the previous ... but it's not.
// The compiler is still happy: because abc was declared as type
// "reference to A1" and A1 is a superclass of B1.
// But the runtime will complain "A1 cannot be cast to B1" and that's
// because the thing being referenced by abc (and o) is NOT a B1 -
// abc's value was created with new A1().
B1 ab2 = (B1)abc;
ab2.amethod();
ab2.bmethod();
// This is the same as the previous.
// The compiler is happy, the runtime is not. And for the same
// reasons.
// Before you run it try to guess the runtime error message.
// "A1 cannot be cast to B1" or "Object cannot be cast to B1"
// Remember how the value that o has was created (the expression
// used to create it).
B1 ab3 = (B1)o;
ab3.amethod();
ab3.bmethod();