【问题标题】:Weird error when using foreach loop in java在java中使用foreach循环时出现奇怪的错误
【发布时间】:2023-03-13 15:24:01
【问题描述】:

我正在开发一个小 todolist 程序,但我遇到了一个以前从未有过的奇怪错误。我有 4 个类:1 个包含待办事项数据的 POJO 类:

public class Todo implements Comparable {
  private String title;
  private String task;
  private boolean done;

  public Todo(String title, String task) {
    this.title = title;
    this.task = task;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String newTitle) {
    title = newTitle;
  }

  public String getTask() {
    return task;
  }

  public void setTask(String newTask) {
    task = newTask;
  }

  public boolean isDone() {
    return done;
  }

  public void setDone(boolean isDone) {
    done = isDone;
  }

  public int compareTo(Object obj) {
    Todo todo = (Todo) obj;
    return getTitle().compareTo(todo.getTitle());
  }

  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("Todo {\n");
    sb.append("Title: \"");
    sb.append(getTitle() + "\";\n");
    sb.append("Task:  \"");
    sb.append(getTask() + "\";\n");
    sb.append("}");
    return sb.toString();
  }
}

然后我有一个类来存储和加载我的待办事项:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class ListStorage {
  Gson gson = new GsonBuilder().setPrettyPrinting().create();
  FileWriter writer;
  BufferedReader reader;

  public void storeList(List list, String filename) throws IOException {
    String json = gson.toJson(list);
    writer = new FileWriter(filename);
    writer.write(json);
    writer.close();
  }

  public List loadList(String filename) throws FileNotFoundException {
    reader = new BufferedReader(new FileReader(filename));
    List list = gson.fromJson(reader, List.class);
    return list;
  }
}

然后我有一个基本上是我的控制器的“经理”类:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Manager {
  private List<Todo> todos = new ArrayList<>();
  private ListStorage storage = new ListStorage();

  public List getTodos() {
    return todos;
  }

  public void setTodos(List newTodos) {
    todos = newTodos;
  }

  public ListStorage getStorage() {
    return storage;
  }

  public void add(String title, String task) {
    todos.add(new Todo(title, task));
    sort();
    try {
      storage.storeList(todos, "todos");
    } catch(Exception e) {
      e.printStackTrace();
    }   
  }

  public void remove(int index) {
    todos.remove(index);
    sort();
    try {
      storage.storeList(todos, "todos");
    } catch(Exception e) {
      e.printStackTrace();
    } 
  }

  private void sort() {
    Collections.sort(todos);
  }
}

最后是用于测试我的代码的主类(错误似乎在这里):

class CLITodo {
  public static void main(String[] args) {
    Manager man = new Manager();

    man.add("Hello", "Bye");
    man.add("Foo",   "Bar");
    try {
      man.setTodos(man.getStorage().loadList("todos"));
    } catch(Exception e) {

    }
    java.util.List<Todo> todos = man.getTodos();
    for (Todo t : todos) {
      System.out.println(t);
    }
  }
}

当我在 CLITodo 类中离开 &lt;Todo&gt; 时收到的错误消息是:

Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to Todo at CLITodo.main(CLITodo.java:13)

当我在 CLITodo 中删除 &lt;Todo&gt; 时,我收到此错误:

CLITodo.java:13:19: error: incompatible types
    for (Todo t : todos) {
                  ^
  required: Todo
  found:    Object

为什么会出现这个错误?我的管理器类 getTodos()-Method 返回一个 Todo 类型的列表,但编译器告诉我它只是一个对象(它当然是,但它也是一个集合,它应该实际工作)。 这是第一次出现这个错误,我真的找不到是什么原因造成的。

【问题讨论】:

  • 我不确定这是您的真实代码。 man.getTodos() 返回一个 List,但您试图将其分配给 List&lt;Todo&gt;...
  • 将 getTodos()-methods 类型更改为 List 如果这就是您的意思,也不起作用

标签: java arraylist foreach


【解决方案1】:

当您没有指定用于反序列化 JSON 的嵌套类型时,就像您在此处所做的那样

List list = gson.fromJson(reader, List.class); // All it knows is that the root json is a List

Gson 使用LinkedTreeMap

你真正想要的是

List list = gson.fromJson(reader, new TypeToken<List<Todo>>(){}.getType());

【讨论】:

  • 这行得通,并且列表正在正确打印出来;非常感谢先生!
  • @selim 不客气。作为旁注,不要使用原始类型。它们会引起各种头痛。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 2016-05-31
  • 1970-01-01
  • 2016-03-07
  • 2020-08-30
相关资源
最近更新 更多