Java: объект как значение в HashMap перезаписывается?

Я добавляю/редактирую объекты, которые являются значениями в хэш-карте с разными ключами.

Однако редактирование одного объекта в хэш-карте, похоже, редактирует их все (?)

Что я здесь делаю неправильно?

Во-первых, мой (плохо названный) класс hashmap:

import java.util.HashMap;
public class hashmap {

static HashMap<Integer, exObj> hm;

hashmap(){
    hm = new HashMap<Integer, exObj>();
}
public void createVal(){
    for (int i = 0; i<10; i++){
        hm.put(i, new exObj(i));
    }
    hm.get(2).setValue();
}
public void printVal(){
    for (int i = 0; i<10; i++){
        System.out.println(hm.get(i).getValue());
    }
}
public static void main(String args[]){
    hashmap hmap = new hashmap();
    hmap.createVal();
    hmap.printVal();    
}

}

Во-вторых, мой простой класс exObj:

public class exObj {

private static int value;

exObj(int i){
    value = i;
}

public void setValue(){
    value = value + 1;
}

public int getValue(){
    return value; 
}

}

возвращает вывод:

10
10
10
10
10
10
10
10
10
10

person quannabe    schedule 02.04.2013    source источник


Ответы (3)


У вас есть статические данные, которые являются общими для всех экземпляров класса.

Попробуйте изменить свой класс, чтобы иметь данные экземпляра (т.е. просто удалить статические данные на private int value).

person Jeff Foster    schedule 02.04.2013
comment
Поскольку он использует exObj только как значение, а не как ключ, в HashMap нет необходимости переопределять hashCode и equals. - person Jesper; 02.04.2013

Это потому, что value в вашем классе exObj это static:

public class exObj {

private static int value;

Поскольку это static, существует только одна копия переменной, которая является общей для всех объектов exObj.

См. Общие сведения об экземплярах и членах классов.

person Jesper    schedule 02.04.2013
comment
Понятно — я не знал, что все объекты имеют общие статические переменные! - person quannabe; 02.04.2013
comment
@quannabe В этом смысл static полей. Лучше не использовать их с изменяемыми данными. - person Tom Hawtin - tackline; 02.04.2013

Как сказали @Jeff Foster и @Jesper, все дело в использовании статической переменной. Просто чтобы добавить дополнительную информацию о вашем примере, запустив код

for (int i = 0; i<10; i++){
    hm.put(i, new exObj(i));
}

последний exObj, который инициализируется, получает значение «9», которое является общим для всех экземпляров. Затем, позвонив

hm.get(2).setValue();

значение установлено как «10»

Вы можете просто объявить «значение» как

private int value;

поэтому каждый экземпляр exObj будет иметь свое значение. Также не забудьте, что имена ваших классов должны начинаться с заглавной буквы, это является хорошей практикой.

person yannicuLar    schedule 02.04.2013