5

我第一次在学校项目中使用泛型,我遇到了一个哲学困境,即在我的方法中是返回对象还是我声明的泛型元素。

我的强迫症告诉我,我需要始终返回已知类型,但我发现这样做会在我将原始数据类型提供给我的类时产生一些下游的烦恼(当然,对于这个项目,我只提供原始数据类型进入这个类)。

这是我的意思的一个例子:

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 会强制我强制转换我的整数值:

DansPriorityQueue<Integer> dpq = new DansPriorityQueue<Integer>();
dpq.add(1);
assertEquals("Expected different value", (Integer) 1, dpq.peek());

另一方面,当我返回一个对象时,自动装箱不会强制我转换我的原始值。

这是对我一直面临的问题的更雄辩的描述:

http://www.aschroder.com/2009/10/php-1-java-0-the-method-assertequalsobject-object-is-ambiguous-for-the-type/

- - - - - - 编辑 - - - - - - - -

这是我在返回泛型类型并用自动装箱的整数对象填充列表时收到的实际错误,而没有上面的强制转换:方法 assertEquals(String, Object, Object) 对于 DansPriorityQueueTest 类型不明确

--------- 结束编辑-------------

问题

  1. 谁能告诉我为什么我应该或不应该返回一个对象,而不是我正在使用的通用元素?两者似乎都有优点和缺点......最佳做法是什么?

  2. 我模糊地知道返回一个对象可能会在以后导致一些铸造问题,但我还没有遇到它们......有没有人有一个具体的例子来说明这有多危险?

  3. 在 JDK 中,我注意到许多 Collections 方法默认返回 Object。这是因为泛型是在 Java 的更高版本中引入的,还是 Sun Systems 有意识的决定?

4

1 回答 1

8

谁能告诉我为什么我应该或不应该返回一个对象,而不是我正在使用的通用元素?两者似乎都有优点和缺点......最佳做法是什么?

这取决于。在这种情况下,您想要泛型类型 - 否则为类定义泛型类型有什么意义?

我模糊地知道返回一个对象可能会在以后导致一些铸造问题,但我还没有遇到它们......有没有人有一个具体的例子来说明这有多危险?

当然!

DansPriorityQueue<String> queue = new DansPriorityQueue<String>();
//add items
Float f = (Float)queue.getObject();  //uh-oh! this compiles but will fail 
Float f = queue.getObject(); //generic type, fails during compile

在 JDK 中,我注意到许多 Collections 方法默认返回 Object。这是因为泛型是在 Java 的更高版本中引入的,还是 Sun Systems 有意识的决定?

这主要是由于向后兼容性,或者在您真正将使用集合来包含不同值的情况下(例如,用于呈现 JTable 的 JLabels、字符串和图标的混杂)。

assertEquals("预期不同的大小", (Integer) 2, dpq.size());

我不认为这应该是一个问题。dpq.size() 应该只返回一个 int ,而不管优先级队列中存储的内容。它不会是一个通用值。

您可以创建类似的东西

DansPriorityQueue<Double> queue = new DansPriorityQueue<Double>();
for(double d = 0; d < 10; d+=1.0)
    queue.add(d);

这应该不会引起任何问题,对吧?

于 2013-11-08T16:00:41.200 回答