This discussion is archived
14 Replies Latest reply: Dec 27, 2008 8:46 PM by 807589 RSS

Casting Problem

807589 Newbie
Currently Being Moderated
Hi All,
I am unable to understand a very simple casting conversion of classes. Please help me clear my concept.!!!
Here is the code.

Employee.java
-------------

code:


public class Employee {
     
     private String name;
     private double salary;
     
     public Employee(String n, double s){
          name = n;
          salary = s;     
     }

     public String getName() {
          return name;
     }

     public void setName(String name) {
          this.name = name;
     }

     public double getSalary() {
          return salary;
     }

     public void setSalary(double salary) {
          this.salary = salary;
     }
     
     public void raiseSalary(double percent){
          double raise = salary * percent / 100;
          salary += raise;
     }
}



Manager.java
------------

code:


public class Manager extends Employee{
     
     private double bonus;
     
     public Manager(String n,double s){
          super(n,s);
          bonus = 0;
     }
     
     public double getSalary(){
          double baseSalary = super.getSalary();
          return baseSalary + bonus;
     }
     
     public void setBonus(double b){
          bonus = b;          
     }
}



ManagerTest.java
----------------

code:


public class ManagerTest {

     public static void main(String[] args) {
          // TODO Auto-generated method stub
          Manager boss = new Manager("Carl Cracker",80000);
          boss.setBonus(5000);
          
          Employee[] staff = new Employee[3];
          
          staff[0] = boss;
          staff[1] = new Employee("ABC",1000);
          staff[2] = new Employee("DEF",2000);
          
          for(Employee e : staff)
               System.out.println("name="+e.getName()+" salary="+e.getSalary());
          
          Manager manager = (Manager)staff[0];
          
          Manager manager1 = (Manager)staff[1]; //Why this gives an error
     }
}



Please help me in understanding this code. This code is shaking my concept of Object conversion type casting. [banghead]

Thanks in advance.
  • 1. Re: Casting Problem
    611651 Newbie
    Currently Being Moderated
    new Employee creates an Employee, not a Manager

    you can cast what you want,but you can only get what you create
  • 2. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    What is staff[1]?

    I'll tell you. It is:
        staff[1] = new Employee("ABC", 1000);
    an Employee, not a manager. So casting a base class as a super class will never work when the underlying object is not a super class object.
  • 3. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    But we do cast superclass objects to subclass references. Like for example in the following code.

    code:


    class A1{
         
         public void amethod(){
              System.out.println("In method A");
         }
    }


    class B1 extends A1{
         
         public void bmethod(){
              System.out.println("In B method");
         }
         
    }


    public class CastText {

         public static void main(String[] args) {
              
              Object o = new A1();
              
              A1 abc = (A1)o;
         
              A1 a1 = new B1();
              
              B1 ab = (B1)a1;
              ab.amethod();
              ab.bmethod();
              
         }

    }



    This example works wherein we are :
    1) typecasting superclass reference (o) to the subclass object (A1)
    Object o = new A1();
    A1 abc = (A1)o;

    2) The same thing we are typecasting the superclass reference (a1) to the subclass object (B1) and its methods are being called ab.method() and ab.bmethod()


    Its very confusing please help me ....
  • 4. Re: Casting Problem
    611651 Newbie
    Currently Being Moderated
    // Create A1 store as super class Object
    Object o = new A1();
    // Cast to A1 subclass
    A1 abc = (A1)o;

    // Create B1 store as super class A1
    A1 a1 = new B1();
    // Cast to B1 subclass
    B1 ab = (B1)a1;

    Object is the superclass of every object
    A1 extends Object
    B1 extends Object is that confusing you?
  • 5. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    No, what I am being confused with is that If I am able to do :

    1) Object o = new A1();
    A1 abc = (A1)o;

    wherein I am typecasting a superclass reference to a subclass object. This in not giving any problem here.

    2) A1 a1 = new B1();
    B1 ab = (B1)a1;

    The same thing is happening here I am typecasting a superclass reference to a subclass object. This is also not giving any problem in runtime.

    SO why do I get a ClassCast Exception in the following :

    Employee[] staff = new Employee[3];
              
    staff[0] = boss;
    staff[1] = new Employee("ABC",1000);
    staff[2] = new Employee("DEF",2000);

    Manager manager = (Manager)staff[0];
    Manager manager1 = (Manager)staff[1]; //Why this gives an error :(


    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 :(
  • 6. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    When I run your code, I see the following:
    {noformat}
    name=Carl ******* salary=85000.0
    name=ABC salary=1000.0
    name=DEF salary=2000.0
    Exception in thread "main" java.lang.ClassCastException: Employee cannot be cast to Manager
         at ManagerTest.main(ManagerTest.java:19)
    {noformat}
    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.
  • 7. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    So why don't I get an error here

    // Create A1 store as super class Object
    Object o = new A1();
    // Cast to A1 subclass
    A1 abc = (A1)o;

    Here o is not a A1 so why don't I get an error here. :(   Here also in runtime abc is pointing to A1 so it should be reasonably OK. But it isn't. Very Very confusing.


    // Create B1 store as super class A1
    A1 a1 = new B1();
    // Cast to B1 subclass
    B1 ab = (B1)a1;

    Here also a1 is not a B1 so why don't I get an error here. :(  Here also in runtime ab is pointing to B1 so it should be reasonably OK. But it isn't.


    Please explain me this anomaly.


    Object is the superclass of every object
    A1 extends Object
    B1 extends Object is that confusing you?
  • 8. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    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;
  • 9. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    Thanks very very much for you explanation !!! Its getting a little clearer.

    Please explain me with this example also as you explained in the previous post. This will help in clearing my concept much better. Thanks a lot again.

    class A1{
         
         public void amethod(){
              System.out.println("In method A");
         }
    }


    class B1 extends A1{
         
         public void bmethod(){
              System.out.println("In B method");
         }
         
    }


    public class CastText {

         public static void main(String[] args) {
              
              Object o = new A1();
              A1 abc = (A1)o;
         
              A1 a1 = new B1();
              B1 ab = (B1)a1;
              ab.amethod();
              ab.bmethod();
              
         }

    }
  • 10. Re: Casting Problem
    796440 Guru
    Currently Being Moderated
    siddharth.bhargava wrote:
    Please explain me with this example also as you explained in the previous post.
    What exactly are you having trouble understanding?
  • 11. Re: Casting Problem
    796440 Guru
    Currently Being Moderated
    siddharth.bhargava wrote:
    No, what I am being confused with is that If I am able to do :

    1) Object o = new A1();
    A1 abc = (A1)o;
    The "o" reference variable points to an A1 object. Therefore, it is legal to cast "o" from "reference to Object" to "reference to A1."
    wherein I am typecasting a superclass reference to a subclass object. This in not giving any problem here.

    2) A1 a1 = new B1();
    B1 ab = (B1)a1;
    If B1 is a subclass of A1, then thisis the same as #1.
    SO why do I get a ClassCast Exception in the following :

    Employee[] staff = new Employee[3];
              
    staff[0] = boss;
    staff[1] = new Employee("ABC",1000);
    staff[2] = new Employee("DEF",2000);

    Manager manager = (Manager)staff[0];
    Manager manager1 = (Manager)staff[1]; //Why this gives an error :(
    Because not every Employee is a Manager. This is different than the above examples because the object is not a Manager object. You can't turn an object into something it's not by casting.

    What you're doing here is the same as this:
    Object obj = new Object();
    String str = (String)obj;
  • 12. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    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();
  • 13. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    Crossposted: [http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=022431].

    Please don't do that in the future.
  • 14. Re: Casting Problem
    807589 Newbie
    Currently Being Moderated
    Thanks a lot. Its clear now. :)