tags:

views:

183

answers:

6

Hi,
just for my understanding. Does my example code below actually changes the the color of my Car Object in the IntHashtable or does the first line creates another instance of the car object, which contains color = red after the second line?

thanks,
Henrik

Car myCar = (Car)myIntHashTable.get(index);   
myCar.setColor = red;

Edit:
Is there a better way than this?

((Car)myIntHashTable.get(index)).setColor = red;
+2  A: 

It actually changes the value in the hash table. Note that if what you're doing changes a key object's hashCode or equals return values, you could be in a world of hurt. Changing just the hash table's value, on the other hand, is usually ok.

Paul Tomblin
+4  A: 

It changes the attribute setColor into what red points to. So the object in your hash table gets changed.

A little demo:

import java.util.*;

public class Main {

  public static void main(String[] args) {
    List<Foo> foos = new ArrayList<Foo>();
    foos.add(new Foo());
    foos.add(new Foo());
    foos.add(new Foo());
    System.out.println("foos="+foos);
    foos.get(1).n = 1;
    System.out.println("foos="+foos);
  }

  static class Foo {
    int n = 0;
    @Override 
    public String toString() {
      return String.valueOf(n);
    }
  }
}

will produce:

foos=[0, 0, 0]
foos=[0, 1, 0]

As you can see, there also is no need for casting when using generics.

Bart Kiers
Thanks! It's J2ME so there is no generics support :(
Henrik P. Hessel
Ah J2ME, I see (not going for Android? :)). And you're welcome, of course!
Bart Kiers
Currently working on a blackberry project ;)
Henrik P. Hessel
+1  A: 

To answer your second question, if you are able to define what the hashtable is:

Hashtable<Integer, Car> myHashTable = new Hashtable<Integer, Car>();

myHashTable.add(1, theCar);

myHashTable.get(1).setColor(red);
tster
Your example is wrong, because you cannot use primitive types such as `int` for generic types. Use `Integer` instead, i.e. `Hashtable<Integer, Car>`.
Jesper
Thanks, I'll update. (I've been spoiled by .NET)
tster
+1  A: 

It changes the value of the 'Color' property of the Car instance stored in the table; a new value is not created.

You don't show a type for myIntHashTable. Note that java.util.Map is typically preferred over the legacy java.util.Hashtable. The latter does locking.

Also, are you indexing these cars by consecutive integral values? If so, you might want some form of List.

You probably want something like this:

final Map<Integer, Car> cars = new HashMap<Integer, Car>();
final Car someCar = new Car();
cars.put(1, someCar);
final Car carInTable = cars.get(1). // refers to same object as someCar
carInTable.setColor(red);

A List implementation is similar:

final List<Car> cars = new ArrayList<Car>();
final Car someCar = new Car();
cars.add(someCar);
final Car carInTable = cars.get(1). // refers to same object as someCar
carInTable.setColor(red);

Sans Generics, just do the casting yourself:

final Map cars = new HashMap();
final Car someCar = new Car();
cars.put(1, someCar);
final Car carInTable = (Car) cars.get(1). // refers to same object as someCar
carInTable.setColor(red);

final List cars = new ArrayList();
final Car someCar = new Car();
cars.add(someCar);
final Car carInTable = (Car) cars.get(1). // refers to same object as someCar
carInTable.setColor(red);

You can always compare object references with == when in doubt about whether two objects are the same object:

System.println.out("someCar and carInTable are " + ((someCar == carInTable) ? "" : "not ") + "the same object");
Greg Mattes
+1  A: 

My stock recommendation for this question is to read the following two articles:

  1. Cup Size -- a story about variables
  2. Pass-by-Value Please (Cup Size continued)

Is there a better way than this?

Which do you find more readable? I think the first is.

mlk
+4  A: 

Variables of non-primitive types are references, so in your example myCar is a reference to the Car object in the hash table. When you change the value of the member variable setColor through the reference myCar, you are changing the contents of the Car object that's in the hash table.

If myIntHashTable is a normal java.util.Hashtable or java.util.HashMap, no copy of your Car object is made.

Some additional notes:

  • Use HashMap instead of Hashtable. Hashtable is a legacy collection class, which has (for almost all purposes) been replaced by HashMap.
  • It's a bit strange that your class Car apparently has a public member variable called setColor. Don't make member variables public, and don't give them strange names such as setColor.

About the last point: Put a private member variable color in your class Car and implement a setColor method:

public class Car {
    private Color color;

    public void setColor(Color color) {
        this.color = color;
    }

    // ...
}

// Somewhere else:
myCar.setColor(Color.RED);
Jesper
But coming vom C++ and C#, in java there is no way to actually change a reference manually, isn't there?
Henrik P. Hessel
What do you mean exactly? You can make a reference point to a different object; just assign something else to `myCar`, for example `myCar = new Car();`.
Jesper