Метод HashMap.put не работает, несмотря на инициализацию HashMap - PullRequest
0 голосов
/ 19 сентября 2018

Мы делаем текстовое приключение, где вы читаете в макете из файла JSON.Я читаю в файле JSON для создания класса Layout, который содержит объекты комнаты.В каждой комнате есть карта направлений, которая отображает название направления (т. Е. Юг, восток, запад и т. Д.) На объект направления.Внутри класса макета есть еще одна карта, которая отображает имена комнат на объект комнаты.Когда я запускаю свой код, отладчик говорит мне, что моя roomMap, так же как и directionMap, равны нулю.Поэтому, когда я пытаюсь вызвать тест JUnit, чтобы убедиться, что при доступе к картам возвращается правильное значение, я получаю исключение NullPointerException.

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;

public class Room {

// instance variables
protected String name;
protected String description;
protected Item[] items;
protected Direction[] directions;

protected ArrayList<Direction> testList = new ArrayList<>();
protected HashMap<String, Direction> directionMap = new HashMap<>();

public Room(String name, String description, Direction[] directions, Item[] items) {
    this.name = name;
    this.description = description;
    this.items = items;
    this.directions = directions;
    for (Direction d : directions) {
        directionMap.put(d.directionName, d);
    }
}

}

Это мой класс управления:

package com.example;

import com.sun.org.apache.xpath.internal.operations.Bool;

public class Direction {

// instance variables
protected String room;
protected String directionName;
protected boolean enabled;
protected String[] validKeyNames;


public Direction(String room, String directionName, String enabled, String[] validKeyNames) {
    this.room = room;
    this.directionName = directionName;
    this.enabled = Boolean.parseBoolean(enabled);
    this.validKeyNames = validKeyNames;
}


public static boolean compareDirections (Direction d1, Direction d2){
    boolean roomMatch = d1.room.equals(d2.room);

    boolean nameMatch = d1.directionName.equals(d2.directionName);

    boolean enabledMatch = d1.enabled == d2.enabled;

    boolean validKeyNamesMatch = true;

    if(d1.validKeyNames.length == d2.validKeyNames.length){
        for(int i = 0; i < d1.validKeyNames.length; i++){
            if(!d1.validKeyNames[i].equals(d2.validKeyNames[i])){
                validKeyNamesMatch = false;
            }
        }
    }

    return roomMatch && nameMatch && enabledMatch && validKeyNamesMatch;
}

}

Это мой класс игрока:

public class Player {

protected Item[] items;
protected Room currentRoom;

public Player(Item[] items, Room startingRoom){
    this.items = items;
    this.currentRoom = startingRoom;
}

}

Это мой класс Предметов:

public class Item {
protected String name;

public Item(String name){
    this.name = name;
}

public static boolean compareItems (Item i1, Item i2){
    return i1.name.equals(i2.name);
}

}

А это мой класс макета, где roomMap равен

public class Layout {

// instance variables
protected String startingRoom;
protected String endingRoom;
protected Room[] rooms;
protected Player player;

protected HashMap<String, Room> roomMap = new HashMap<>();


public Layout(String startingRoom, String endingRoom, Room[] rooms, Player player) {
    this.startingRoom = startingRoom;
    this.endingRoom = endingRoom;
    this.rooms = rooms;
    this.player = player;

    for (Room room : rooms) {
        roomMap.put(room.name, room);
    }
}

Это класс чтения JSON:

public class JsonReader {

public static String getJsonFromUrl (String link) throws IOException {
    try{
        URL url = new URL(link);
    } catch(MalformedURLException e){
        System.out.println("That is not a valid link");
        System.exit(0);
    }
    URL url = new URL(link);
    // Connect to the URL using java's native library
    URLConnection request = url.openConnection();
    request.connect();

    // Convert to a JSON object to print data
    JsonParser jp = new JsonParser(); //from gson
    JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
    JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
    return rootobj.toString();
}

}

Я протестировал синтаксический анализатор Gson и знаю, что все значения из файла JSON правильно сериализуются, поэтомуЯ запутался, что пара ключ-значение не помещается в hashmap.

Вот мои JUnit-тесты

import com.google.gson.Gson;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.IOException;

import static org.junit.Assert.*;

public class AdventureTest {


Adventure adventure;

@Before
public void setup() {
    adventure = new Adventure("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd");
}

@Test
public void getJsonFromUrlTest() throws IOException {
    assertEquals(
            "{\"startingRoom\":\"SDRPCommons\",\"endingRoom\":\"HopkinsRoom345\",\"rooms\":[{\"name\":\"SDRPCommons\",\"description\":\"You are in the Ikenberry Dining Hall. There is good food, good people, and good study areas\",\"directions\":[{\"directionName\":\"North\",\"room\":\"DiningHall\",\"enabled\":\"false\",\"validKeyNames\":[\"I-card\"]},{\"directionName\":\"Northwest\",\"room\":\"UpstairsArea\",\"enabled\":\"true\",\"validKeyNames\":[]},{\"directionName\":\"West\",\"room\":\"OutsideAreaOfSixPack\",\"enabled\":\"false\",\"validKeyNames\":[\"backpack\",\"depression\"]}],\"items\":[{\"name\":\"I-card\"},{\"name\":\"Chair\"},{\"name\":\"Fork\"}]},{\"name\":\"DiningHall\",\"description\":\"The best eats on campus, other than PAR/FAR, Chomps, and basically anything on Green Street.\",\"directions\":[{\"directionName\":\"South\",\"room\":\"SDRPCommons\",\"enabled\":\"true\",\"validKeyNames\":[\"depression\"]}],\"items\":[{\"name\":\"sweatshirt\"},{\"name\":\"key\"}]},{\"name\":\"UpstairsArea\",\"description\":\"You are upstairs. Near you is Caffeinator but it's closed. So there is nothing to do but to go back to your room and grind...\",\"directions\":[{\"directionName\":\"Southeast\",\"room\":\"SDRPCommons\",\"enabled\":\"true\",\"validKeyNames\":[]}],\"items\":[{\"name\":\"depression\"},{\"name\":\"backpack\"}]},{\"name\":\"OutsideAreaOfSixPack\",\"description\":\"It's a beautiful day and everyone is out and about. Kinda makes you want to sit in your room in the dark, right?\",\"directions\":[{\"directionName\":\"North\",\"room\":\"HopkinsRoom345\",\"enabled\":\"false\",\"validKeyNames\":[\"depression\",\"backpack\"]}],\"items\":[{\"name\":\"depression\"},{\"name\":\"backpack\"}]},{\"name\":\"HopkinsRoom345\",\"description\":\"This is your room. Go inside and grind your cs 126 hw, idiot.\",\"directions\":[{\"directionName\":\"South\",\"room\":\"OutsideAreaOfSixPack\",\"enabled\":\"false\",\"validKeyNames\":[\"key\",\"depression\"]}],\"items\":[{\"name\":\"bed\"}]}]}",
            JsonReader.getJsonFromUrl("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd")
    );
}

@Test
public void loadJsonIntoLayout() throws IOException {
    String json = JsonReader.getJsonFromUrl("https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd");
    Gson gson = new Gson();
    Layout layout = gson.fromJson(json, Layout.class);
    if (layout != null) {
        assertEquals("SDRPCommons", layout.startingRoom);

        //  System.out.println(layout.roomMap.get(layout.startingRoom));
        Room r = adventure.roomMap.get("DiningHall");
        Direction d = adventure.directionMap.get("south");
        String s = d.directionName;
        assertEquals("south", layout.roomMap.get("DiningHall").directionMap.get("south"));
    }
}

}

Это класс приключений:

import com.google.gson.Gson;
import java.io.*;
import java.lang.reflect.Array;
import java.net.*;
import java.util.*;

import static sun.plugin.javascript.navig.JSType.Element;

public class Adventure {

protected Layout layout;
protected HashMap<String, Room> roomMap = new HashMap<>();
protected HashMap<String, Direction> directionMap = new HashMap<>();
//    private Player player;
private static String jsonUrl;
// link for easy access: https://drive.google.com/uc?export=download&id=1qmmrC3jZ3zrmdvrL8ukM5r4pB4BYhfyd
protected Room currentRoom;

protected final List<String> ACTION_VERBS = Arrays.asList("go");
protected final List<String> EXIT_VERBS = Arrays.asList("exit", "quit");
protected final List<String> ITEM_VERBS = Arrays.asList("pickup", "use");


public Adventure(String url) {
    this.jsonUrl = url;
    this.layout = getLayoutFromJson(jsonUrl);
    String startingRoom = layout.getStartingRoom();
    for (Room r : layout.rooms) {
        for (Direction d : r.directions) {
            r.directionMap.put(d.directionName, d);
        }
        layout.roomMap.put(r.name, r);
    }
    this.currentRoom = roomMap.get(startingRoom);
}

public Layout getLayoutFromJson(String url) {
    try {
        String json = JsonReader.getJsonFromUrl(url);
        Gson gson = new Gson();
        Layout layout = gson.fromJson(json, Layout.class);
        return layout;
    } catch (Exception e) {
        return null;
    }
}

}

1 Ответ

0 голосов
/ 19 сентября 2018

Gson не собирается автоматически вызывать конструктор не по умолчанию.Либо он вызывает конструктор без аргументов, либо он «автоматически» создает экземпляр из ничего, а затем заполняет его поля с помощью отражения.Читать Является ли конструктор по умолчанию без аргументов для Gson обязательным?

Это означает, что ваш код заполненности roomMap / directionMap не будет вызываться, так как этот код находится внутри конструкторов не по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...