Java 正确存储和管理(反)序列化对象,以及如何在反序列化后使用它们

Java 正确存储和管理(反)序列化对象,以及如何在反序列化后使用它们,java,libgdx,transient,Java,Libgdx,Transient,我想使用具有保存/加载功能(反序列化)的类中的数据将多个对象加载并渲染到游戏世界,但我不知道如何正确地将它们重新引入到程序中,因为它们包含渲染/显示它们所必需的瞬态对象 我第一次运行程序时,它试图从一个名为“data.txt”的txt文件加载数据,但该文件不存在。该程序创建一个新的Data.txt文件,向其中添加一个名为“Campfire”的Campfire对象并保存它。只要程序运行,它就会被渲染到屏幕上(这部分工作正常)。关闭程序并重新启动程序后,应该检查文件,找到它并加载ArrayList“

我想使用具有保存/加载功能(反序列化)的类中的数据将多个对象加载并渲染到游戏世界,但我不知道如何正确地将它们重新引入到程序中,因为它们包含渲染/显示它们所必需的瞬态对象

我第一次运行程序时,它试图从一个名为“data.txt”的txt文件加载数据,但该文件不存在。该程序创建一个新的Data.txt文件,向其中添加一个名为“Campfire”的Campfire对象并保存它。只要程序运行,它就会被渲染到屏幕上(这部分工作正常)。关闭程序并重新启动程序后,应该检查文件,找到它并加载ArrayList“data”,其中包含以前保存/序列化的campfire对象。然后,它向其中添加另一个相同类型的对象,并渲染这两个对象。这部分在我的Campfire类的render方法中抛出一个NullPointerException

这是主要课程:

public class MainClass extends ApplicationAdapter{
public static SpriteBatch batch;    

private Data data;
private Campfire campfire;

@Override
public void create () {
    batch = new SpriteBatch();

    data = new Data();
    data.load();

    campfire = new Campfire();
    data.addCampfire(campfire);

    System.out.println(data.getSize());
    data.save();
}

@Override
public void render () {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.begin();
        data.render(batch);
    batch.end();
}
加载所有文件的类:

public class Data {
private String filename;
private ArrayList<Campfire> data;

 public Data() {
    data = new ArrayList<Campfire>(); 
    filename = "Data.txt"; 
 }

 public void save(){
     try {  
         FileOutputStream file = new FileOutputStream (filename); 
         ObjectOutputStream out = new ObjectOutputStream (file);       

         out.writeObject(data); 
         out.close(); 
         file.close();      
     }catch (IOException e) {e.printStackTrace();} 
 }

public void load() {
     try {                                  
         FileInputStream file = new FileInputStream (filename); 
         ObjectInputStream in = new ObjectInputStream(file); 

         data = (ArrayList<Campfire>)in.readObject();  
         in.close(); 
         file.close();  
     } 
     catch (IOException io) {System.out.println("File not found.");} 
     catch (ClassNotFoundException ex) {System.out.println("Cant load from file.");}
 } 

 public void addCampfire(Campfire object) {
     data.add(object);
 }
 public void render(SpriteBatch batch) {
     for(int i = 0;i < data.size(); i++) {
         Campfire camp = data.get(i);
         camp.render(batch);
        //data.get(i).render(batch);
     }
 }

 public Campfire get(int index) {
    return data.get(index);
 }

 public void set(int index, Campfire object) {
     data.set(index, object);
 }

 public int getSize() {
     return data.size();
 }
原因是纹理“img”不存在,因为我需要使用transient关键字,因此它不会保存/加载到数据文件中

我需要一种不同的方法来根据从中加载的数组列表创建对象。我无法处理arrayList中的对象,因为它们无法渲染(必须将transient关键字指定给Texture()对象-它不可序列化)。我已经看了很多教程,并阅读了大量关于这个主题的文章,但我找不到一篇提到如何重新引入对象的文章,这样我就可以利用它依赖于不可(反)序列化部分的函数

我的问题是: 有没有比我的尝试更好的方法(再次创建对象,然后将反序列化的值分配给它?在反序列化过程之后,我不知道如何正确地加载和使用“data”ArrayList,我感谢关于如何将它们重新引入程序的每一条建议

提前感谢,,
M

我建议不要为此使用java序列化。它在序列化格式的大小方面可能有优势,但根据我的经验,使用它有点困难。您遇到过这种困难,因为您无法序列化
纹理
对象,因为它不可
序列化
。您避免了通过将其标记为瞬态来解决问题,这是一个错误。处理您不拥有的对象可能有一些变通方法-注册一些处理程序,但我不知道细节,因为我避免了它

取而代之的是一种友好的格式,比如json,这意味着你的序列化数据文件会大一点,但是,你可以打开并读取它,看看你保存了什么

还有…libgdx附带了一些工具。请查看他们的wiki页面,了解使用情况

还有其他选择,比如谷歌的gson库,但为什么不坚持使用libgdx的工具呢?我发现它们非常可靠


只是一个额外的警告-如果你在Android中使用某种代码模糊/最小化工具,你需要将其配置为不重命名任何你序列化的对象,因为它确实依赖于包和对象名称进行反序列化。如果你保存游戏状态,这也是需要注意的-然后更改名称/包,然后尝试加载该游戏状态。

我建议不要为此使用java序列化。它在序列化格式的大小方面可能有优势,但根据我的经验,使用它有点困难。您遇到过这种困难,因为您无法序列化
纹理
对象因为它不是
可序列化的
。您通过将其标记为瞬态来避免问题,这是一个错误。处理您不拥有的对象可能有一些解决方法-注册一些处理程序,但我不知道细节,因为我避免了它

取而代之的是一种友好的格式,比如json,这意味着你的序列化数据文件会大一点,但是,你可以打开并读取它,看看你保存了什么

还有…libgdx附带了一些工具。请查看他们的wiki页面,了解使用情况

还有其他选择,比如谷歌的gson库,但为什么不坚持使用libgdx的工具呢?我发现它们非常可靠


只是一个额外的警告-如果你在Android中使用某种代码模糊/最小化工具,你需要将其配置为不重命名任何你序列化的对象,因为它确实依赖于包和对象名称进行反序列化。如果你保存游戏状态,这也是需要注意的-然后更改名称/包,然后尝试加载该游戏状态。

感谢您为我指明了正确的方向。您的答案和链接帮助了我很多!感谢您为我指明了正确的方向。您的答案和链接帮助了我很多!
public class Campfire implements Serializable{
private transient Texture img;
private int id;

public Campfire() {             
    img = new Texture("campfire.png");
}

public void render(SpriteBatch batch) {
    batch.draw(img, 200,200, 2000,2000);
}