微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于“Effective Java Item#29 Favor Generic Types”中解决方案#1“堆污染”的问题

如何解决关于“Effective Java Item#29 Favor Generic Types”中解决方案#1“堆污染”的问题

我正在阅读 Effective Java Item#29 Favor Generic Types。

我对这个项目在谈到选择解决方案#1或解决方案#2的原因时提到的堆污染感到困惑。

消除通用数组创建的两种技术都有其 信徒。第一个更具可读性:数组被声明为 输入E[],明确表示只包含E个实例。这是 也更简洁:在典型的泛型类中,您从数组中读取 在代码中的许多地方;第一种技术只需要一个 强制转换(创建数组的位置),而第二个需要一个 每次读取数组元素时单独转换。因此,第一 技术更可取,在实践中更常用。它确实, 然而,导致堆污染(Item 32):数组的运行时类型 不匹配其编译时类型(除非 E 恰好是 Object)。 这让一些程序员感到非常不安,以至于他们选择了 第二种技术,虽然堆污染在这里是无害的 情况。

在我的理解中,这意味着一些程序员可能会担心解决方案#1 处的“堆拉拔”,因此他们可能会选择解决方案#2。 我的理解正确吗? Java 专家能否帮我弄清楚为什么在解决方案#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
}

解决方法

在解决方案#2 中,您必须在 pop 方法中强制转换不推荐的内容。您的代码不是类型安全的。如果方法更复杂,则可能会产生错误。因为它,你没有任何好处。

另一个类似的例子是方法get。你也必须投:

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。