关于“有效java项目29偏好泛型类型”中解决方案1中“堆污染”的问题

kyks70gy  于 2021-09-13  发布在  Java
关注(0)|答案(1)|浏览(258)

我正在阅读有效的java项目#29,喜欢泛型类型。
我对这个项目在谈到选择解决方案1或解决方案2的原因时提到的堆污染感到困惑。
这两种消除通用数组创建的技术都有其追随者。第一个更具可读性:数组被声明为e[]类型,明确表示它只包含e示例。它也更简洁:在一个典型的泛型类中,您在代码中的多个点读取数组;第一种技术只需要一次转换(创建数组的地方),而第二种技术每次读取数组元素时都需要一次单独的转换。因此,第一种技术更可取,在实践中更常用。但是,它确实会导致堆污染(第32项):数组的运行时类型与其编译时类型不匹配(除非e恰好是对象)。这使得一些程序员非常不安,他们选择了第二种技术,尽管在这种情况下堆污染是无害的。
在我看来,这意味着一些程序员可能会担心解决方案1的“堆污染”,所以他们可能会选择解决方案2。我的理解正确吗?javaMaven能帮我弄清楚为什么堆污染会发生在解决方案1或解决方案2上吗?
没有泛型的原始代码

// Object-based collection - a prime candidate for generics
public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(Object e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private void ensureCapacity() {
        if (elements.length == size)
            elements = Arrays.copyOf(elements, 2 * size + 1);
    }
}

通用解决方案#1

public class Stack<E> {
    private E[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
    }

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0)
            throw new EmptyStackException();
        E result = elements[--size];
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }
    ... // no changes in isEmpty or ensureCapacity
}

通用解决方案#2

public class Stack<E> {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY]; 
    }

    public void push(E e) {
        ensureCapacity();
        elements[size++] = e;
    }

    public E pop() {
        if (size == 0)
            throw new EmptyStackException();
        E result = (E) elements[--size];
        elements[size] = null; // Eliminate obsolete reference
        return result;
    }
    ... // no changes in isEmpty or ensureCapacity
}
gupuwyp2

gupuwyp21#

在解决方案2中,您必须在pop方法中使用不推荐的方法。您的代码不是类型安全。如果方法更复杂,可能会产生错误。你没有任何好处,因为它。
另一个类似的例子是get方法。你还必须投:

public E get(int n) {
    return (E) elements[n];
}

相关问题