我正在创建几个函数,我想在其中返回接口而不是实现,I.E。列表而不是ArrayList。我的方法签名和简要实现如下:
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>)
{
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
{
MyAwesomeComposedObject composedObject = new MyAwesomeComposedObject(awesomeObject);
composedObjects.add(composedObject);
}
List<MyAwesomeComposedObject> composedObjectList = Collections.checkedList<composedObjects, MyAwesomeComposedObject.class);
return composedObjectList;
}
我的问题是,这是某种反模式吗?我想保证这个方法的调用者获取接口而不是实现。我也不认为这是过度工程的情况。如果这不是返回接口的正确方法,那么在这种情况下,我可以接受正确的实现。
附件是一个导致异常的小程序:
public static void main(String[] args)
{
Vector v = (Vector) c();
}
static List<Object> c()
{
List<Object> l = new ArrayList<Object>();
l.add(new Object());
List<Object> o = Collections.checkedList(l, Object.class);
return o;
}
javadoc在这里:checked list
答案 0 :(得分:2)
返回的List是Collections.CheckedList而不是Vector。你不能引用对象不是的类型。
然而,你可以做的是
public static void main(String[] args) {
Vector<Object> v = new Vector<Object>(c());
}
composedObjects已经是一个List,你可以返回它。
public List<MyAwesomeComposedObject> convert(Collection<MyAwesomeObject> awesomeObjects>) {
List<MyAwesomeComposedObject> composedObjects = new ArrayList<MyAwesomeComposedObject>();
for(MyAwesomeObject awesomeObject : awesomeObjects)
composedObjects.add(new MyAwesomeComposedObject(awesomeObject));
return composedObjects;
}
答案 1 :(得分:1)
对于您修改过的问题:无法阻止调用者尝试强制转换为他们想要的任何内容。如果是不合适的演员,他们将获得例外。这就是为什么强烈建议不要从接口到具体类的强制转换的原因。
如果您真的对此感到担心,请考虑返回ArrayList
而不是List
。这应该阻止铸造,因为他们正在得到一个具体的类型。请注意,我不认可这一点,这只是一个选择。
我想保证此方法的调用者获取接口而不是实现
这是无效的。您返回List
,其中元素的声明类型是接口,但每个元素必须是SOME实例化。所有已检查的集合都会阻止添加不正确类型的元素。没有什么可以阻止用户回退到实现类型。
如果您尝试确保用户获得List
而不是ArrayList
(我的假设是因为我没有看到您的Awesome类的界面),这又是有缺陷的,因为用户仍然可以将List
转换为ArrayList
,但这可能是一个坏主意,因为它会冒ClassCastException
的风险。
答案 2 :(得分:0)
不,我建议尽可能简化代码。阅读Javadoc以了解何时使用Collections.checkedList
的讨论