Java 为什么要在内部使用MyObject[],但要公开一个列表<;MyObject>;?
我遇到了一个具有不可变属性的类:Java 为什么要在内部使用MyObject[],但要公开一个列表<;MyObject>;?,java,arrays,collections,Java,Arrays,Collections,我遇到了一个具有不可变属性的类: MyObject[] allObjs 属性的初始化方式如下: List<MyObject> objs = createAllMyObjects(); allObjs = objs.toArray(new MyObject[objs.size()]); List objs=createAllMyObject(); allObjs=objs.toArray(新的MyObject[objs.size()]); 当它通过访问器公开时,它作为一个列表完成
MyObject[] allObjs
属性的初始化方式如下:
List<MyObject> objs = createAllMyObjects();
allObjs = objs.toArray(new MyObject[objs.size()]);
List objs=createAllMyObject();
allObjs=objs.toArray(新的MyObject[objs.size()]);
当它通过访问器公开时,它作为一个列表完成:
public List<MyObject> getAllMyObjects() {
return Collections.unmodifiableList(Arrays.asList(allObjs));
}
public List getAllMyObjects(){
返回集合.unmodifiableList(Arrays.asList(allObjs));
}
程序员为什么要这样做?有我不知道的好处吗
性能并不是一个问题,因为OBJ数组只会包含几十个元素
我们似乎在兜圈子
该类是一种工厂,因此它有一个私有构造函数,只公开静态方法(不确定这是否是疯狂的原因)
编辑
我想我的问题是,“为什么不使用一个内部的
列表allObjs
而不是MyObject[]allObjs
,并返回集合。不可修改列表(allObjs)?”因为这将完成同样的事情。我认为使用数组代替列表没有任何好处。列表要舒服得多。也许这家伙只是喜欢使用数组:)我认为这背后的原因可能是数组是不可修改的。但是,您可以将内部列表保留为列表,并在getter中返回它的副本,这样内部列表仍然无法从外部修改
或者使用集合返回的“不可修改”列表。不可修改列表()
在这种情况下,我也看不到任何性能优势,因为来回转换需要一些周期。这样集合就不可修改,即调用方无法修改成员数组。
无法对数组执行此操作,因此编码人员会将其复制到列表中。似乎编写者有意返回一个不可变的副本,并且重复了此操作。我假设选择了一个列表作为返回类型,这样就可以使用MyObject类型轻松创建克隆。有一个很好的理由不返回对内部
MyObject[]
属性的引用。通过引用,调用者可以对数组进行更改
如果没有理由认为结果必须是列表
,您也可以返回数组的副本:
public MyObject[] getAllMyObjects() {
MyObject[] result = new MyObject[allObjs.length];
system.ArrayCopy(allObjs, 0, result, 0, result.length);
return result;
}
更新,添加问题后:
如果将内部属性更改为列表,则将其包装为不可修改会更容易,这是正确的
类使用数组而不是列表的原因可能是性能。如果数组在对象的生命周期内没有变化(很多),并且多次迭代,那么数组的开销比列表小
如果性能是使用数组的原因,则可以通过存储列表来防止在getter中创建额外的对象,这只是为了返回,即:
allObjsList = Collections.unmodifiableList(createAllMyObjects());
allObjs = allObjsList.toArray(new MyObject[allObjsList.size()]);
像前面一样使用allObjs数组,并在getter中返回存储的列表:
public List<MyObject> getAllMyObjects() {
return allObjsList ;
}
public List getAllMyObjects(){
返回allObjsList;
}
我看到的唯一原因是“在误用的情况下尽早失败”(如果这个设计选择不是随机的并且有意义,那么意思是他很少信任他的特定客户)
MyObject[]
是具体化的,并在运行时检查,而列表
不是。可以在后者中隐藏非MyObject引用(当然,他在编译时会得到未检查的警告),这将在未定义的将来某个点失败,出现ClassCastException
,但他不能对MyObject[]
,这将在误用点立即失败
但是请注意,如果客户机是在泛型之前使用此API的预构建二进制文件,那么没有人会收到未检查的警告,因此如果此代码试图迁移泛型前客户机使用的代码,这是有意义的
(实现相同结果的另一种方法是使用List
,还需要Class
,以便后者可以提供运行时类型检查。但这需要另一个构造函数参数,例如,现有客户端不会自动利用该参数。**更新:*这基本上描述了API调用mSauer在第一篇评论中提到,因此我们不必重新发明这个,只需使用那个:)。在书中,作者实际上说,既然我们有泛型,我们应该只使用collection,而不应该再使用array。就我个人而言,我现在倾向于远离数组,因为集合可以帮助我记住我使用一个集合的意图,例如,将集合与列表作为数组的对立面,而数组并不能真正告诉我关于数据的任何信息
此外,除了快速复制(System.arraycopy())之外,我对集合没有什么不能做的事情,这可能有以下几个原因:
- 他们不知道自己在做什么。我现在从事的代码似乎是由Java新手和编程新手编写的。不幸的是,遇到设计拙劣的代码远比找到由对平台有深入了解的人编写的好的、干净的、维护良好的代码要普遍得多。这部分是因为下一点
更改已修补,但不想进行大规模更改。如果代码的其余部分使用该数组,则可能有人不想费心进行所有其他更改列表
- 虽然集合是更为面向对象/Java的处理方式,但如果列表是静态的,那么数组实际上“更容易”使用,因为它们仍然可以像集合一样使用
进行迭代,但可以使用for(:)
而不是[]
进行访问。就我个人而言,这不是使用数组的充分理由,但也许这只是我自己get()
- 也许吧