【问题标题】:HashMap saving with ObjectOutputStream使用 ObjectOutputStream 保存 HashMap
【发布时间】:2012-08-07 12:22:12
【问题描述】:

为了在命令中保存传送点,我有一个HashMap

public HashMap<Player, Location> mapHomes = new HashMap<>();

访问方式如下:

if(cmd.getName().equalsIgnoreCase("sethome")){
    Location loc = player.getLocation();
    mapHomes.put(player, loc);
    sender.sendMessage("Home set !");
    return true;
}
if(cmd.getName().equalsIgnoreCase("home")){
    Location loc1 = mapHomes.get(player);
    player.teleport(loc1);
    sender.sendMessage("Teleported to home");
    return true;
}
return false;

由于这些设置应该在重启时保持,我实现了一个保存方法:

public void save(HashMap<Player,Location> mapHome, String path) throws NotSerializableException{
    try{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
        oos.writeObject(mapHome);
        oos.flush();
        oos.close();
    }catch(Exception e){
        e.printStackTrace();
    }
}

但它不起作用。它抛出NotSerializableException

我认为主要问题是PlayerLocation 不是可序列化的类型,那么我应该怎么写这个HashMap

【问题讨论】:

    标签: java serialization objectoutputstream bukkit


    【解决方案1】:

    HashMap 已经是Serializable

    问题是地图内的对象不是,所以你也必须让它们可序列化。

    public class SerializedPlayer extends Player implements Serializable {
        public SerializedPlayer() {}
        public SerializedPlayer(Player playerToClone) {
            this.setField1(playerToClone.getField1());
            // Set all the fields
        }
    }
    

    添加到地图时:

    map.put(new SerializedPlayer(player), new SerializedLocation(location));
    

    【讨论】:

      【解决方案2】:

      当实例需要有Serializable 接口时抛出NotSerializableException

      class YourClass implements Serializable {
          // ...
      }
      

      【讨论】:

        【解决方案3】:
        class Player implements Serializable {}
        
        class Location implements Serializable {}
        

        请记住,您只能序列化实现Serializable 接口的对象。 所以你的PlayerLocation 类也必须实现接口。

        【讨论】:

          【解决方案4】:

          我认为您正在将HashMap&lt;Player, Location&gt; 写入文件。

          您需要做的是使您的 PlayerLocation 类可序列化。

          public class Player implements java.io.Serializable {
              // ...
          }
          
          public class Location implements java.io.Serializable {
              // ...
          }
          

          HashMap 已经可以序列化了。

          【讨论】:

            【解决方案5】:

            要使Location 可序列化,我建议使用this class。 我自己写的,只是请求你在代码中给我信用。

            package com.github.JamesNorris.Class;
            
            import java.io.Serializable;
            import java.util.HashMap;
            import java.util.Map;
            
            import org.bukkit.Bukkit;
            import org.bukkit.Location;
            import org.bukkit.Server;
            import org.bukkit.World;
            
            /**
             * The class that allows location to be serialized, and be used
             * in a file. This class should not be changed, otherwise it
             * will not work for older files.
             * 
             * @author Jnorr44
             */
            
            public final class SerializableLocation implements Serializable {
                private static final long serialVersionUID = 8650311534439769069L;
            
                private final String world;
                private final String uuid;
                private final double x, y, z;
                private final float yaw, pitch;
                private transient Location loc;
            
                /**
                 * Creates a new SerializableLocation instance of any org.bukkit.Location.
                 * 
                 * @param l
                 */
            
                public SerializableLocation(Location l) {
                    this.world = l.getWorld().getName();
                    this.uuid = l.getWorld().getUID().toString();
                    this.x = l.getX();
                    this.y = l.getY();
                    this.z = l.getZ();
                    this.yaw = l.getYaw();
                    this.pitch = l.getPitch();
                }
            
                /**
                 * Gets the org.bukkit.Location back from any SerializableLocation.
                 * 
                 * @param l
                 * @return
                 */
            
                public static Location returnLocation(SerializableLocation l) {
                    float pitch = l.pitch;
                    float yaw = l.yaw;
                    double x = l.x;
                    double y = l.y;
                    double z = l.z;
                    World world = Bukkit.getWorld(l.world);
                    Location location = new Location(world, x, y, z, yaw, pitch);
                    return location;
                }
            
                // FROM HERE ON NEEDS DOC NOTES
            
                public SerializableLocation(Map<String, Object> map) {
                    this.world = (String) map.get("world");
                    this.uuid = (String) map.get("uuid");
                    this.x = (Double) map.get("x");
                    this.y = (Double) map.get("y");
                    this.z = (Double) map.get("z");
                    this.yaw = ((Float) map.get("yaw")).floatValue();
                    this.pitch = ((Float) map.get("pitch")).floatValue();
                }
            
                public final Map<String, Object> serialize() {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("world", this.world);
                    map.put("uuid", this.uuid);
                    map.put("x", this.x);
                    map.put("y", this.y);
                    map.put("z", this.z);
                    map.put("yaw", this.yaw);
                    map.put("pitch", this.pitch);
                    return map;
                }
            
                public final Location getLocation(Server server) {
                    if (loc == null) {
                        World world = server.getWorld(this.uuid);
                        if (world == null) {
                            world = server.getWorld(this.world);
                        }
                        loc = new Location(world, x, y, z, yaw, pitch);
                    }
                    return loc;
                }
            }
            

            现在只需这样做:

            SerializableLocation loc = new SerializableLocation(LOCATION);
            

            之所以需要这样做是因为Location 包含worldxyzyawpitch,其中world 不可序列化。

            【讨论】:

              【解决方案6】:

              实际上,您正在尝试序列化PlayerLocation,尝试实现新类等。但是您为什么要这样做?

              最好不要存储PlayerLocation 对象,而是存储它们的字符串表示形式。例如,您可以使用Player.getName()"world:100:65:100"之类的东西来定位(这样我们就可以轻松通过String.split(":") 获取所有数据。我认为这是更好的方法。

              【讨论】:

                猜你喜欢
                • 2021-02-26
                • 2016-03-20
                • 2013-04-03
                • 2014-08-19
                • 1970-01-01
                • 1970-01-01
                • 2013-04-14
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多