3

My code looks like this:

public class Hashtabledemo2 {

public static void main(String[] args) {

    Hashtable myCompay = new Hashtable(10);
    System.out.println("Add some employee objects to the hashtable..");

    Salary e1 = new Salary("Salary1", "Palo Alto, CA",
            1, 100000.00);
    Hourly e2 = new Hourly("Hourly2", "Cupertino, CA", 2, 100.00);

    Contractor e3 = new Contractor("Contractor3", "Milpitas, CA",3, 1000.00);

    myCompay.put(new Integer(e1.hashCode()), e1);
    myCompay.put(new Integer(e2.hashCode()), e2);
    myCompay.put(new Integer(e3.hashCode()), e2);

    System.out.println("The size of the hashtable is "+myCompay.size());

    int size = myCompay.size();

    for(int i=1;i<=size;i++){
    /* Note that the get() method of the  hashtable class returns a reference to the object
        that matches the given key:
         public Object get(Object key)
         */
        Employee current =  (Employee) myCompay.get(new Integer(i));



        if(current instanceof Hourly){ 
            ((Hourly) current).setHoursWorked(40);
        } else if(current instanceof Contractor){

            ((Contractor) current ).setDaysWorked(5);
        }
        current.computePay();
        current.mailCheck();

    }

Salary, hourly, and contractor all extend the employee class.In my understanding we cast parent references to child ones not the other way round.I don't understand how this line of code works:

Employee current =  (Employee) myCompay.get(new Integer(i));

this line of code is used to get the object stored at position one of the hashtable which is a Salary object.

myCompay.get(new Integer(i));

After that it is cast to Employee:

(Employee) myCompay.get(new Integer(i));

and then assigned to an Employee reference current:

Employee current =  (Employee) myCompay.get(new Integer(i));

Could someone explain to me whether we are casting the object salary stored in the hashtable to an employee object and then assigning it to a employee reference current.or are we casting the reference e1 to an employee reference. Someone explain what is going on please.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
kobewarui
  • 73
  • 1
  • 8

4 Answers4

5

The difference between objects and references in Java is somewhat blurred, because the only way to access an object is through a reference. When you do casting, you make a reference of a different types to the same object.

Note that your code is broken: it puts objects into a hash table using their raw hash codes, but then it tries to retrieve them back using their sequence numbers. This is not expected to work, unless you get lucky, and one of the objects returns a hash code in the range 0..3.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    "but then it tries to retrieve them back using their sequence numbers"- Thanks i think you,v explained enough with that line .Then whats the alternative of putting objects into a hashtable without using their raw hash codes ? So that means if you use raw hash codes to store,you must use raw hash codes to retrive ? – kobewarui Jul 30 '15 at 11:52
  • @kobewarui There are no situations outside of programming the *internals* of a hash table when you would want to call `hashCode()` and use the result directly. If you want to put data into a hash table, give each entry a unique key that your code controls. It could be a string, an integer, or some other key object that you can quickly construct, and then use to retrieve the entry. Since your code is using sequence numbers to retrieve data, you should use the same sequence numbers to put the data into the table. – Sergey Kalinichenko Jul 30 '15 at 12:07
  • @kobewarui Of course if all you need is the retrieval of an object by its sequence numbers, you do not need a hash table at all: a simple list or an array would be sufficient. – Sergey Kalinichenko Jul 30 '15 at 12:08
  • Thanks that explains quite alot but could you take a look at "thedarknessbeckons" answer and explain to me why he says this "You cannot assign an object instance of type Object to a reference of type Employee".I thought the object instance being returned by the get() method is of type salary and not of type object? Because thats the first object i stored in the hashtable,with this lines of code : Salary e1 = new Salary("Salary1", "Palo Alto, CA", 1, 100000.00); myCompay.put(new Integer(e1.hashCode()), e1); – kobewarui Jul 30 '15 at 12:24
  • @kobewarui His comment is not related to your code. Of course in your case there is a reference of type `Object` coming out, but it refers to `Employee`, so the assignment is valid after the cast. He means something like this: `Employee e = new Object();` This assignment would remain invalid with or without the cast: without the cast it wouldn't compile, and with the cast it would fail at runtime. – Sergey Kalinichenko Jul 30 '15 at 12:29
  • " Of course in your case there is a reference of type Object coming out, but it refers to Employee" - I understand that but if you mean the reference being returned is of type employee why then should you cast it into an employee if it already is an employee reference.Directly answer this question,what is being returned by this code: myCompay.get(new Integer(i)); ? – kobewarui Jul 30 '15 at 13:02
  • 1
    @kobewarui The reference type is determined by `get(...)` method's return type, which is `Object`. The thing the `Object` refers to happens to be of type `Employee`, though, so the cast would be allowed. `get(new Integer(i))` would return whatever is stored at the key `new Integer(i)`, or `null` if the key is not part of the hash table. – Sergey Kalinichenko Jul 30 '15 at 13:06
  • Thats the exact answer i have been looking for all along,i dint look up the get method in the java api to know its return type is of type object.Thanks man how do i upvote you !!!!!! – kobewarui Jul 30 '15 at 13:15
2

With casting you only change the type of the reference, the object behind it will stay the same.


You could cast Contractor to Employee (but there is no need for that, since you can already access everything from Employee), You can also cast Employee to a Contractor, then you can access the Contractor-Methods and Fields (only if the object behind Employee is a Contractor, otherwise you'll get an exception).

You cant cast an Contractor to an Hourly since they not extend each other. Casting an Contractor to an Employee and then to an Hourly will produce an Exception, since the object behind it is still an Contractor

hinneLinks
  • 3,673
  • 26
  • 40
  • Actually, this is false. You are not changing the type of the reference either. What you are actually doing is >>checking<< the type if the reference / object – Stephen C Jul 30 '15 at 10:57
1

You have a few misconceptions:-

Salary, hourly, and contractor all extend the employee class.

This is not what inheritance is for. Only Contractor could be considered a type of Employee. Salary and Hourly should be properties of an Employee (lookup Composition).

Also, as dasblinkenlight stated, your retrieval is also misunderstood since the key is looked up based on its hash. Lookup hashcode and equals contract.

As for your actual question. As you already understand, get returns an Object from this raw Hashtable. You cannot assign an object instance of type Object to a reference of type Employee since this would then allow you to invoke Employee's behaviours (methods) on that instance and the Object class does not know anything about what an Employee can and cannot do. So the cast to (Employee) is actually a check on the actual type of the object that get has returned to check whether it can legally be assigned to the Employee reference.

However, you should not use raw types as of Java 5. Generics provides you with type safety. Lookup Generics and why you should not use raw types.

jacks
  • 4,614
  • 24
  • 34
  • You might have employees who have a permanent salary and those that are paid hourly hence the need for salary and hourly classes,to compute their pay would be different.Why is it that your calling it raw ? rather than just a hashtable ? How does the object being returned by the get() method become of type Object ? because i remember while i was putting it in the hashtable it was a salary object ? check this line of code: Salary e1 = new Salary("Salary1", "Palo Alto, CA", 1, 100000.00); and this line also :myCompay.put(new Integer(e1.hashCode()), e1); – kobewarui Jul 30 '15 at 12:03
  • when modelling Employees, classes such as Rate (hourly, daily) and EmployeeType (contract, perm) etc make perfect sense. The point is they are Not Types of Employee - they are attributes of an Employee. If you read some basic tutorials on Inheritance, Composition etc this will make more sense. To understand "raw" in this context check out the docs - https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html. To understand why a "raw" collection returns instances as type Object read http://stackoverflow.com/questions/2770321/what-is-a-raw-type-and-why-shouldnt-we-use-it – jacks Jul 30 '15 at 15:27
0

what you actually do is to cast the reference returned by the hashtable, then assign it to a reference. notice that casting does not change the object (or the refenrece) - it only tells the program to "treat" the casted entity as the type you casted to.

David Haim
  • 25,446
  • 3
  • 44
  • 78
  • The reference being returned is e1 which references a salary object in my thinking: Salary e1 = new Salary("Salary1", "Palo Alto, CA", 1, 100000.00); and this line also :myCompay.put(new Integer(e1.hashCode()), e1); .I thought when going up the inheritance hierarchy, no casting is needed. For example, a Salary reference can be used to invoke an Employee method without casting because Employee is a parent of Salary. Going down the hierarchy.This is what am imagining is happenin: Employee current = (Employee) e1. – kobewarui Jul 30 '15 at 12:14
  • in the java world, explicit actions are always required. it's supposed to prevent you to make mistakes – David Haim Jul 30 '15 at 12:17