我第一次在学校项目中使用泛型,并遇到了一个哲学上的困境,即是否在我的方法中返回对象或已声明的泛型元素。我的强迫症告诉我需要始终返回已知类型,但我发现这样做会在将基本数据类型输入类时创建一些下游烦恼(当然,在此项目中,我只将基本数据类型输入到该类中)。以下是我所说的例子:
当我返回一个对象时,自动装箱不会强制我进行基本类型转换。以下是对我面临的问题更为优美的描述:
public class DansPriorityQueue<E extends Comparable>
{
private ArrayList<E> tree;
//Here's a method that returns an object
public Object peek() {
return tree.get(0);
}
//Here's a method that returns the generic type
public E peek() {
return tree.get(0);
}
作为一种补充说明.. 我需要自己实现这个JDK类,但幸运的是我不需要实现真正的PriorityQueue所使用的相同接口,因此我可以选择是否要使用Object或泛型。
我的问题
这让我感到有点不舒服,但我很想只返回一个Object而不是我的E泛型元素,因为当我返回E时,JUnit会强制我将整数值转换为int类型:
DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());
当我返回一个对象时,自动装箱不会强制我进行基本类型转换。以下是对我面临的问题更为优美的描述:
------------编辑----------------
当我返回泛型类型并使用自动装箱的整数对象填充列表时,如果没有进行上述强制转换,我会收到以下实际错误:该方法assertEquals(String,Object,Object)对于DansPriorityQueueTest类型是模糊的。
--------- 结束编辑--------------
问题
有人能告诉我为什么应该或不应该返回对象,而不是我正在处理的通用元素吗?两者似乎都有优缺点...最佳实践是什么?
我大致知道返回对象可能会在以后引起一些转换问题,但我还没有遇到这些问题...有人有具体的危险示例吗?
在JDK中,我注意到许多集合方法默认返回对象。这是因为泛型是在Java的较新版本中引入的,还是Sun Systems做出的有意决定?
dpq.size()
声明了什么作为其返回类型?我有点困惑,因为您的示例使用了一个似乎根本没有使用peek()
的调用,所以不确定我是否理解其相关性。size()
不是集合元素类型上通用的方法。 - Mark PetersassertEquals()
有几个重载版本,例如:assertEquals(Object, Object)
和assertEquals(int, int)
。当自动装箱使得你的意思不明确时,需要进行强制类型转换,例如:assertEquals(42, new Integer(42))
。编译器应该将第一个装箱还是将第二个拆箱?(记住,编译器并不知道实际上这并不重要)。我通过让所有单元测试都扩展我的自己的BaseTest extends TestCase
类来解决这个问题,并使用assertInteger(int exp, int act) { assertEquals(exp, act); }
。 - Paul