java - 尽管已初始化 HashMap,但 HashMap.put 方法仍不起作用
问题描述
我们正在进行基于文本的冒险,您可以从 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);
}
}
这是我的房间地图所在的布局类
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 文件中的所有值都被正确序列化,这就是为什么我对键值对没有放在哈希图中感到困惑的原因。
这是我的 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;
}
}
}
解决方案
Gson 不会自动调用非默认构造函数。它要么调用无参数构造函数,要么“自动”无中生有地创建一个实例,然后通过反射填充其字段。阅读Gson 是否必须使用默认的无参数构造函数?
这意味着您的roomMap
/directionMap
人口代码不会被调用,因为该代码位于非默认构造函数中。
推荐阅读
- d3.js - 地图未渲染,但数据正确
- sql - 在 R 中使用 json 文件读取数据帧
- sql - 使用休眠创建接受多个空值的唯一索引
- java - 在 android studio 中找不到符号错误
- javascript - 在服务中可观察与仅使用 this.service Angular 7
- r - 无法在 tidytext 中使用 NRC 词典。match.arg(lexicon) 中的错误:“arg”应该是“afinn”、“bing”、“loughran”之一
- java - 带有 Elasticsearch 6.4.2 的 Spring 数据不适用于 Java hashmap 属性
- mysql - SQL SERVER 通过字段之间的数学运算排序
- c++ - 在类中存储指向 sqlite3 数据库的指针会引发段错误
- python - 抽象方法:如何使代码在类定义上失败,而不是实例创建?