在数组中存储多个类型时,创建类型为Object的Array或创建新类是更好的Java实践吗?

时间:2013-11-05 22:27:45

标签: java arrays performance

假设我有对象类型A,B和C.我想将它们存储在一个数组中。一种方法是这样的:

A a = new A();
B b = new B();
C c = new C();

Object[] array = {a, b, c};

从设计角度来看,这不太理想,因为您现在需要知道数组[0]是A类型,但与Ruby或Python等允许此类事物的语言不同。

也就是说,另一种选择是创建一个自定义类D来保存该信息:

private class D {
    public A myA;
    public B myB;
    public C myC;

    public D(A a, B b, C c) {
       //...
    }
}

D[] otherArray = new D[1];
otherArray[0] = new D(a, b, c);

哪种方法更好?出于设计原因,我可以看到第二种方法的论点(尽管如此,其他语言一直都在讨论这个问题)。

从性能的角度来看,第一种方法的必要的上行/下行是否比重复创建新的D对象更昂贵,反之亦然?

4 个答案:

答案 0 :(得分:5)

Java是一种类型安全的OO语言。使用类和对象。所以你的第二个解决方案要好得多(除了我不明白为什么你需要一个1元素的D数组)。

表现无关紧要。两者都可能同样快(对于第二种解决方案而言具有明显优势),而且无论如何都不会出现性能问题。不要预先优化:它是所有邪恶的根源。

答案 1 :(得分:3)

在构造函数中使用简单参数创建一个新对象意味着性能非常低。存储的数量比保持值分离的多一点,但这实际上只是一个类带来的开销:你甚至不需要考虑它。

第二种解决方案非常优越:它不需要任何铸造,它对于您自己和其他开发人员来说更加清晰,它更灵活,因为它允许您更多地操纵和指导数据等。

Object[]模糊了它所包含的数据,这在很多情况下是一种简单的反模式。

如果ABC位于同一级别的层次结构中(fe:它们都是Car的子类),则可以使用它们在一个数组中。如果它们属于一起构建第三类,则必须将它们分组到一个对象中。

答案 2 :(得分:2)

“最佳做法”是使用语义正确且最适合您需要的方法。

通过“语义”正确我的意思是:您的信息的性质是什么?是假设是通用对象的集合,还是假设是具有A,B和C属性的特定D?

这也意味着代码隐式强制执行不变量和结构,并且含义很明确。如果D应该包含ABC,那么拥有一个带有命名的约束字段的D是有意义的 - 那样你知道D总是有三个指定类型的子对象,读者可以清楚地看到这个对象。如果你实际上正在处理任意大小的语义中性对象集合,那么数组会更清楚地传达你的意图。

如果D应该包含ABC,但您将其表示为Object[],那么您现在必须显式假设或验证不变量,否则这些不变量将在代码中清楚地表达并由编译器强制执行(数组是否具有3个相应类型的元素?)。结果是错误的风险很高,维护和测试的难度很高,以及在必要时检查阵列的有效性会增加复杂性。

“最合适”的意思是与您可能正在使用的任何API完全兼容,并且方便并导致清晰的代码。如果您的API需要Object[]D,那么使用与该API兼容的任何类型都是最方便的。

这实际上取决于你的情况。但一般来说,“最佳实践”是根据您的具体情况使用最有意义,清晰且易于阅读,可测试和可维护的代码。

从性能角度来看,这完全没有实际意义。从绩效角度考虑这一点是错误的。除非您的代码不符合您的性能要求,并且您已将瓶颈识别为与该阵列的类型有某种关系,否则它是无关紧要的。另外,Java中的大多数这样的微优化都是徒劳的,JVM解释器和热点编译器对结果代码的控制远远超过你。

答案 3 :(得分:2)

问题是,在你的第一个案例中,你将如何处理这些价值观?有可能他们有一些共同的行动。在这种情况下,也可以创建一个界面:

interface Giggler {
    public void giggle();    // the common operation
}

现在,使所有可以giggle实现该接口的对象。然后你可以:

// assuming A, B and C implement Giggler
A a = new A(...);
B b = new B(...);
C c = new C(...);
Giggler[] array = new Giggler[] { a, b, c };