简体   繁体   English

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

[英]Question about “heap pollution” at solution#1 in “Effective Java Item#29 Favor Generic Types”

I am reading Effective Java Item#29 Favor Generic Types.我正在阅读 Effective Java Item#29 Favor Generic Types。

I'm confused about heap pollution that this item mentioned when it talked about the reason to choose solution#1 or solution#2.我对这个项目在谈到选择解决方案#1 或解决方案#2 的原因时提到的堆污染感到困惑。

Both techniques for eliminating the generic array creation have their adherents.这两种消除通用数组创建的技术都有其拥护者。 The first is more readable: the array is declared to be of type E[], clearly indicating that it contains only E instances.第一个更易读:数组被声明为 E[] 类型,清楚地表明它只包含 E 个实例。 It is also more concise: in a typical generic class, you read from the array at many points in the code;它也更简洁:在典型的泛型类中,您在代码中的许多点从数组中读取; the first technique requires only a single cast (where the array is created), while the second requires a separate cast each time an array element is read.第一种技术只需要一次转换(创建数组的地方),而第二种技术需要每次读取数组元素时进行单独的转换。 Thus, the first technique is preferable and more commonly used in practice.因此,第一种技术在实践中更可取且更常用。 It does, however, cause heap pollution (Item 32): the runtime type of the array does not match its compile-time type (unless E happens to be Object).但是,它确实会导致堆污染(条款 32):数组的运行时类型与其编译时类型不匹配(除非 E 恰好是 Object)。 This makes some programmers sufficiently queasy that they opt for the second technique, though the heap pollution is harmless in this situation.这让一些程序员非常不安,他们选择了第二种技术,尽管在这种情况下堆污染是无害的。

In my understanding, that means some programmers might concern about "heap pullution" at solution#1, so they might choose solution#2.在我的理解中,这意味着一些程序员可能会担心解决方案#1 处的“堆拉拔”,因此他们可能会选择解决方案#2。 Is my understanind correcyt?我的理解正确吗? Could Java expert help me to figure out why heap pollution might happen at solution#1 or solution#2? Java 专家能否帮我弄清楚为什么解决方案#1 或解决方案#2 会发生堆污染?

Original Code without Generic没有通用的原始代码

// 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);
    }
}

solution#1 for Generic通用的解决方案#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
}

solution#2 for Generic通用的解决方案#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
}

In solution #2 you have to cast in pop method what is not recommended.在解决方案#2 中,您必须在 pop 方法中强制转换不推荐的内容。 Your code is not type-safety.您的代码不是类型安全的。 If methods are more complicated it can generate bugs.如果方法更复杂,则可能会产生错误。 You don't have any benefits because of it.你没有任何好处,因为它。

Another similar example is method get.另一个类似的例子是方法get。 You have to cast also:你还必须投:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM