Почему у HashMap Java разное поведение с разными объектами? - PullRequest
0 голосов
/ 14 марта 2011

У меня есть следующий фрагмент кода Java, использующий HashMap и generics:

import java.util.*;
import java.io.*;

public class Map{
    static HashMap<Integer, Integer> imap;
    static HashMap<Integer, Thing> tmap;

    public static void main(String[] args){

        imap = new HashMap<Integer, Integer>();
        imap.put(0,0);
        Integer i = imap.get(0);
        i = i + 1;
        System.out.println(imap.get(0));

        tmap = new HashMap<Integer, Thing>();
        tmap.put(0,new Thing(0));
        Thing t = tmap.get(0);
        t.a = t.a + 1;
        System.out.println(tmap.get(0).a);
    }
}

class Thing{
    public int a;
    public Thing(int n){
        this.a = n;
    }
}

, который печатает следующее:

0
1

Я ожидаю, что он напечатает оба варианта (если я изменял ссылку) или оба ноля (если я изменял значения)Так почему же поведение для карты отличается от целого числа к целому, чем от целого числа к вещи?

Ответы [ 5 ]

5 голосов
/ 14 марта 2011

Целочисленные типы Java не являются изменяемыми, поэтому ваш первый пример берет значение из карты, а затем заменяет локальную переменную новым значением.Однако второй пример получает ссылку на экземпляр Thing с карты.

1 голос
/ 14 марта 2011

Делая i = i + 1, вы увеличиваете не значение, хранящееся в java.lang.Integer, содержащемся в карте.

0 голосов
/ 14 марта 2011

Отвечая на вторую часть вопроса («Но тогда почему он печатает 1 во втором операторе print?»), Это потому, что строки ...

Thing t = tmap.get(0);
t.a = t.a + 1;

... получить ссылку на объект, расположенный в хэш-карте в заданном месте, а затем изменить переменную-член ссылочного объекта . Затем оператор println извлекает другую ссылку на этот же объект с помощью измененной теперь переменной-члена.

0 голосов
/ 14 марта 2011

Это потому, что вы автоматически распаковываете значение Integer, когда берете его с первой карты (присваивая Integer типу int). В этот момент вы не используете целочисленную ссылку, вы используете примитив int, не связанный с целочисленной ссылкой, хранящейся на карте.

Поскольку целые числа java неизменны, на самом деле нет способа сделать то, что вы пытаетесь продемонстрировать здесь. Невозможно изменить внутренний примитив int, содержащийся в ссылке Integer на карте. Вам нужно будет ввести новое целое число, чтобы изменить значение, хранящееся в ключе 0.

0 голосов
/ 14 марта 2011

Я думаю, что я = я + 1;не будет обновляться для объекта, потому что get будет копией по значению при назначении примитива.Поэтому примитивное обновление не будет отражаться на карте, поскольку вы не держите ссылку.В следующем примере в Thing вы прямо присваиваете общедоступный примитив Thing, опять же по значению - но вы обновляете public int.

...