0

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

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

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

从设计的角度来看,这不太理想,因为您现在需要知道 array[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

4 回答 4

5

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

性能无关紧要。两者可能都一样快(对于第二种解决方案具有轻微的优势),并且无论如何这不是您遇到性能问题的地方。不要预先优化:它是万恶之源。

于 2013-11-05T22:31:44.463 回答
3

在其构造函数中创建具有简单参数的新对象在性能方面意义不大。与保持值分开相比,存储空间要多一些,但这实际上只是类带来的开销:您甚至不必考虑任何事情。

第二种解决方案要好得多:它不需要任何转换,对你自己和其他开发人员来说更清晰,更灵活,因为它允许你更多地操纵和指导数据等等。

Object[]混淆它包含的数据,这在许多情况下是一个简单的反模式。

如果A和位于同一层次结构(fe:它们都是 3 的子类) B,那么它们可以在一个数组中使用。如果它们属于一起构造第三个类,那么它们必须被分组到一个对象中。CCar

于 2013-11-05T22:31:36.517 回答
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 };
于 2013-11-05T22:39:43.817 回答
2

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

“语义上”正确是指:您的信息的性质是什么?它应该是通用对象的集合,还是应该是具有 A、B 和 C 属性的特定 D?

这也意味着代码隐含地强制执行不变量和结构,并且含义是明确的。如果 aD应该有一个A, B, and C,那么有一个D带有命名的、受约束的字段的 a 是有意义的——这样你就知道 aD总是有三个指定类型的子对象,并且对于读者来说意义是清楚的。如果您实际上正在处理任意大小的语义中性对象集合,那么数组会更清楚地传达您的意图。

如果 aD应该有一个A, B,C但您将其Object[]表示为合适的类型?)。结果是错误的高风险和维护和测试的高难度,以及在必要时检查阵列有效性的复杂性。

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

这真的取决于你的情况。不过,总的来说,“最佳实践”是根据您的具体情况使用最有意义、干净、易于阅读、可测试和可维护的代码。

从性能的角度来看,它完全没有实际意义。从性能的角度考虑这一点是错误的。除非您的代码不满足您的性能要求,并且您已经确定瓶颈与此数组的类型有关,否则它是无关紧要的。此外,Java 中的大多数此类微优化无论如何都是徒劳的,JVM 解释器和热点编译器对生成的代码的控制比你做的要多得多。

于 2013-11-05T22:34:53.310 回答