Работа с новым объектом также изменяет ссылку

#java #reference #libgdx

#java #ссылка #libgdx

Вопрос:

У меня есть этот список объектов, который включает массив, который я (хочу) использовать только в качестве ссылки. Поэтому, когда я создаю новый объект, заполняю его массивом в списке и начинаю изменять этот новый объект, я не хочу, чтобы мои начальные массивы для объекта в моем списке менялись.

Я в основном делаю это:

 //Fill list with my reference objects;

Object newObject = new Object(); //So i do not change the previous newObject in the loop.
newObject = (find)ObjectFromList;
newObject.array = RotateArray(newObject.array);
  

Если я заполняю другой newObject тем же объектом из списка, он уже вращается. Надеюсь, я был достаточно ясен. Ниже приведена сокращенная версия моего кода, все еще немного запутанная:

LoadRooms(); // Загружает все объекты и массивы из файла в список.

 for(int x=0;x<width;x  )
        {
            for(int y=0;y<height;y  )
            {
                Room newRoom = new Room();
                //Fill newroom with correct room type, rotate and build tilemap.
                //Dead ends
                if(!mazeMap[x][y].N amp;amp; !mazeMap[x][y].E amp;amp; mazeMap[x][y].S amp;amp; !mazeMap[x][y].W)
                {
                    newRoom = FindRoom(Room.RoomType.DeadEnd);
                    newRoom.room = TurnRoomCW(newRoom.room);
                    newRoom.room = TurnRoomCW(newRoom.room);
                    newRoom.room = TurnRoomCW(newRoom.room);
                }
                else if(!mazeMap[x][y].N amp;amp; mazeMap[x][y].E amp;amp; !mazeMap[x][y].S amp;amp; !mazeMap[x][y].W)
                {
                    newRoom = FindRoom(Room.RoomType.DeadEnd);
                }
                            //Etc, etc then i build a map from the newRoom.room array        
    }
}
  

Вот как выглядит TurnRoom():

 private String[][] TurnRoomCW(String[][] room)
    {
        String[][] rotatedRoom = new String[room[0].length][room.length];
        for (int y = 0; y < room[0].length;y  )
        {
            for (int x = 0;x < room.length;x  )
            {
                rotatedRoom[y][x] = room[7 - x][y];
            }
        }       
        return rotatedRoom;
    }
  

и вот FindRoom

 private Room FindRoom(Room.RoomType roomType)
    {
        Collections.shuffle(rooms, rand);
        for (Room r : rooms)
        {
            if (r.roomType.equals(roomType))
                return r;
        }

        return null;
    }
  

Когда я хочу превратить что-то вроде комнаты углового типа, скажем, NE в правильное положение, все остальные комнаты поворачиваются вместе с ним. Поэтому, когда я захочу повернуть, скажем, SW в положение NE, позиция снова будет неправильной.

Комментарии:

1. Нет, извините: вы недостаточно ясно выразились. Лучшим началом было бы простое изложение вашей проблемы без избыточного кода.

Ответ №1:

Ваш FindRoom метод возвращает ссылку на фактическую комнату. ‘TurnRoomCW’ возвращает новый объект, но затем вы назначаете этот новый объект обратно в исходную комнату

Итак, ваша проблема прямо здесь:

 newRoom = FindRoom(Room.RoomType.DeadEnd); // 1) find a DeadEnd room
newRoom.room = TurnRoomCW(newRoom.room); // 2) create rotated room, assign it to the room from step 1)
  

Если вы хотите работать с новым Room объектом, вам нужно будет каким-то образом создать новый. Например, вы можете определить конструктор Room , который возвращает новый объект, инициализированный из существующего. Например,

 /** copy constructor */
public Room(Room oldRoom) { 
   this(); // regular constructor
   this.room = oldRoom.room.clone(); // new Room gets its own array!
   this.roomType = oldRoom.roomType;
   // … etc for any other member variables
}
  

Ответ №2:

По сути, объекты Java являются ссылками (указателями, если хотите), поэтому, если вы не создадите явную копию массива (или любого другого объекта), он будет указывать на тот же объект.

Если вы хотите избежать этого, вам нужно сначала выполнить клонирование:

 List myList = referenceList.clone();
  

В любом случае, это, как правило, хорошая привычка, позволяющая избежать изменения вашего «внутреннего» объекта внешним миром.

Комментарии:

1. Я попробую это. Но почему: int i = 10; int j = i; j — 1; теперь i по-прежнему равно 10, а j равно 9. Я делаю то же самое в своем коде afaik.

2. У меня нет доступа к методу clone. Я использую ArrayList.

3. ArrayList можно клонировать ( docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html ). Другой вариант выглядит примерно так: newList = new ArrayList(referenceList);