【问题标题】:How to access the objects inside an ArrayList of generic ArrayLists如何访问通用 ArrayLists 的 ArrayList 中的对象
【发布时间】:2012-11-19 14:10:53
【问题描述】:

我是 Java 新手,甚至对 Java 中的泛型也很陌生。我一直在寻找类似的问题,但没有找到针对我的特定问题的直接答案。

我正在开发一个项目来管理患者、医生、咨询、医疗事件以及与医疗诊所相关的所有内容。 我现在要做的是创建一个与每个患者相关的医疗事件列表。对于这个医疗事件列表,目前,它应该只允许添加检查和处方,但它应该是可扩展的:如果我需要,我希望将来能够添加其他类型的医疗事件,例如关于手术的信息。

所以,我首先在 Patient 类中创建了一个通用 ArrayLists 的 ArrayList,它的类型由 MedicalEvent 类扩展(因此,现在,它是一个 Prescription 或 Exam 类型的 ArrayLists 的 ArrayList)。我还创建了一个 Prescription 类型的 ArrayList 和另一个 Exam 类型。

List<ArrayList<? extends MedicalEvent>> medicalevents;

private ArrayList<Prescription> prescriptions;

private ArrayList<Exam> exams;

然后,在构造函数中,我将 ArrayLists 处方和检查添加到 ArrayList 医疗事件中。

medicalevents.add(prescriptions);

medicalevents.add(exams);

为了添加两种允许类型之一的医疗事件,我定义了以下方法:

public void addMedicalEvent(E element){

if(element instanceof Prescription){
    medicalevents.get(0).add((Prescription)element);
    }
if(element instanceof Exam){
    medicalevents.get(1).add((Exam)element);
    }
}

问题是,我收到错误“ArrayList 类型中的方法 add(capture#1-of ? extends MedicalEvent) 不适用于参数(处方)”,我不知道这是什么意思。谁能告诉我我做错了什么,或者提出更好的方法来解决这个问题?

谢谢!

【问题讨论】:

  • PrescriptionMedicalEvent 的孩子吗?
  • 这与您的问题无关,但我认为使用地图> 比拥有需要硬编码索引的列表列表(就像您拥有的那样)要好得多。
  • 您似乎正在尝试创建一个通用的异构集合,我认为这在 Java 中是不可能的(特别是没有任何关于类型安全的编译器警告)。

标签: java generics arraylist


【解决方案1】:

鉴于以下声明

class A {}
class B extends A {}
class C extends A {}


public class SOSample {
    public static void main(String[] args) {
        List<List<? extends A>> list = new ArrayList<List<? extends A>>();
        final List<? extends A> as = list.get(0);
        as.add(new B()); // error here
    }
}

您不能将B 添加到as,因为稍后您将尝试从列表中读取时会导致问题:

A a = list.get(0).get(0); // is a B or C?

为了更好地理解这个问题,有一个有趣的例子:

class Vehicle { void launch(); }
class Car extends Vehicle {}
class NuclearMissile extends Vehicle {}
...
// this is prohibited because of below code
List<? extends Vehicle> cars = new ...
// imagine this is possible...
cars.add(new NuclearMissile());
// now this is possible
cars.get(0).launch();

一般来说,像List&lt;? extends Something&gt; 这样的有界通配符的集合对于不会修改集合的代码很有用,而只是迭代它来处理元素。

关于您的原始问题 - 您可以更改代码,以便有两个不同的列表,一个用于 Prescription,另一个用于 Exam。你仍然可以只使用 一个 方法来遍历这两个列表,做一些有用的事情(比如打印它们的内容):

void doSomethingWithEvents(List<? extends Event> events) {
}

【讨论】:

【解决方案2】:

这样的东西会更好吗?

class Medical {
    List<EventList<?>> eventLists = new ArrayList<EventList<?>>();

    Medical() {
        eventLists.add(new EventList<Perscription>(Perscription.class));
        eventLists.add(new EventList<Exam>(Exam.class));
    }

    boolean add(Object item) {
        for(EventList<?> list : eventLists) {
            if(list.tryToAdd(item)) {
                return true;
            }
        }
        return false;
    }
}

class EventList<T> {
    Class<T> type;
    List<T> list = new ArrayList<T>();

    EventList(Class<T> type) {
        this.type = type;
    }

    boolean tryToAdd(Object item) {
        if(type.isInstance(item)) {
            list.add(type.cast(item));
            return true;
        } else {
            return false;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2011-10-16
    • 1970-01-01
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 2014-03-03
    • 2013-01-12
    • 2016-10-09
    • 1970-01-01
    相关资源
    最近更新 更多