我有一个方法,需要将一个域对象或它们的集合传递给它。传递的参数的处理根据是单个实例还是集合而略有不同。
我可以寻求最佳方法的建议吗?我应该让方法签名接受一个对象类型,然后使用instanceof
进行处理,并按如下所示向下转换吗?
private static synchronized void mymethod(Object obj) {
if (obj instanceof List ) {
...
}
else if (obj instanceof MyObjectClass) {
...
}
}
还是应该使用重载?在每种情况下都有什么陷阱? 我知道第一种情况有点危险,因为它可以接受传递给它的任何内容,但是我的代码并不打算用作API或扩展等。
答案 0 :(得分:3)
针对这种设计“问题”有不同的方法。
使用方法重载:
void myMethod(final MyObject myObject);
void myMethod(final List<? extends MyObject> myObjects);
使用var-args输入参数:
void myMethod(final MyObject... myObject);
-> myMethod(myObject);
-> myMethod(myObject, myOtherObject);
-> myMethod(myObjectsArray); // myObjectsArray = new MyObject[]
使用Collection
/ List
作为输入参数:
void myMethod(final Collection<? extends MyObject> myObjects);
-> myMethod(Collections.singletonList(myObject));
-> myMethod(myObjectCollection); // List<MyObject>, Set<MyObject>, Collection<MyObject>
我个人会使用方法重载,因为内部逻辑通常会稍有改变,但是会改变。目的更加明确,可以为单个方法自定义JavaDoc。
我是一个“挑剔的”开发人员,我更喜欢明确指出可以有两种输入形式。我更喜欢重载,即使(目前)不必要。在那种情况下,我只委托给Collection<?>
方法,或者相反。
void myMethod(final MyObject object) {
myObject(Collections.singletonSet(object));
}
但这是基于观点的。
我想说的最重要的方面是,不要重复代码!
答案 1 :(得分:2)
在这种情况下,过载通常是解决方法。请记住,列表的通用类型实际上是在运行时“擦除类型”,因此您不会真正知道您的List
实际上是List<MyObjectClass>
。重载将为您提供编译时间检查,因此更安全。
在使用泛型时,还请考虑您的MyObjectClass
是否将以某种方式扩展。您可能会得到这些对象的集合。
此外,作为一种通用模式,请尝试避免在两个重载方法中都重复代码。因此,如果在传递List
时对所有对象都执行相同的操作,则可以从另一个方法调用如下方法:
private static synchronized void mymethod(MyObjectClass obj) {
//todo: do the logic on the object
}
private static synchronized void mymethod(Collection<? extends MyObjectClass> collection) {
//assuming the logic is the same, otherwise do whatever you need to do here
collection.forEach(obj -> mymethod(obj));
}
向下转换和instanceof
通常是设计决策的征兆,无法完全满足您的需求。有时很难摆脱它们,而您必须求助于它们,但是通常,理想的是让编译器验证您的类型并针对所需的行为进行正确的方法解析。
答案 2 :(得分:0)
方法重载就可以满足您的需求。我可以想到以下方法
private static synchronized void mymethod(MyObjectClass myObj){
...
}
private static synchronized void mymethod(Collection<MyObjectClass> myObj){
...
}
在我编辑答案时,TreffnonX已经给出了更详细和基于通用的正确方法。引用它:)
答案 3 :(得分:-1)
重载该方法似乎在这里更正确,尽管两个版本都可以使用。这样,编译器可以尽可能地评估代码。但是,老实说,您的代码似乎有点不完整。我个人的方法是走得更远,并用通用类型泛化该方法:
private static synchronized <T extends MyObjectClass> void mymethod(T obj) {
...
}
private static synchronized <T extends MyObjectClass> void mymethod(Collection<T> obj) {
...
}
此版本的优势在于,无论您在mymethod
内做什么,您都可以返回与该类型有关的内容,而现代IDE可以极大地帮助您评估和更好地解决Lambda。
此外,为什么还要专门使用List
? Collection
可以吗?通常,当您将自己限制在列表中时,就会错过Sets
和其他重要收藏。