我确实搜索过,但找不到类似的问题。如果这是重复的,我很抱歉。我编写了一个常规队列方法并尝试将其扩展为具有优先级队列。我不明白为什么我只能在使用父类(super class)的方法时插入,而不是子类中的代码,而 storage[n] 是 Comparable 而 data 也是 Comparable。如果我尝试在子类中这样做,将抛出 ClassCastException。我做错了什么吗?
RegularQueue.java
import java.util.Arrays;
public class RegularQueue<T> {
protected int capacity;
protected T[] storage;
@SuppressWarnings("unchecked")
RegularQueue(int capacity) {
this.capacity = capacity;
storage = (T[]) new Object[this.capacity];
}
@Override
public String toString() {
return "Queue{" +
"capacity=" + capacity +
", storage=" + Arrays.toString(storage) +
'}';
}
void insert(T data) {
storage[0] = data;
}
}
PriorityQueue.java
public class PriorityQueue<T> extends RegularQueue<Comparable<T>> {
PriorityQueue(int capacity) {
super(capacity);
}
// This doesn't work
@Override
void insert(Comparable<T> data) {
storage[1] = data;
}
// ---> This works fine.
// @Override
// void insert(Comparable<T> data) {
// super.insert(data);
// }
public static void main(String[] args) {
PriorityQueue<Integer> q = new PriorityQueue<>(5);
q.insert(1);
System.out.println(q.toString());
}
}
最佳答案
您看到此 ClassCastExpression 是因为在 RegularQueue 中您使用的是非类型安全赋值 storage = (T[]) new Object[this.capacity]
.在 PriorityQueue 中,您使用的是 Comparable<...>
作为 T
的类型参数常规队列。因此在编译时知道这个 T
在运行时必须是 Comparable
或者它的子类型。因此编译器发出 Comparable[]
每次访问 T[] storage
时都会在 PriorityQueue 中转换强制执行此操作。
现在的问题是 storage
实际上不是 T[]
类型但只有 Object[]
类型这导致您看到的 ClassCastException。以任何方式访问该字段时都会发生这种情况,即使是 storage.length
触发它。
您在 insert
中没有看到此异常的原因方法调用 super.insert
是它不直接访问storage
.只有 super 实现会执行此操作,但不会执行任何转换,因为在 RegularQueue 内部类型为 T
在编译时是未知的。
解决方案是不声明storage
作为T[]
而是使用 Object[]
因为这是实际类型。
其他人将此作为错误报告给 JDK 团队,但报告已(如预期)作为“不是问题”得到解决。然而,JDK 开发人员之一斯图尔特·马克斯 (Stuart Marks) 在 his comment 中进行了解释在报告中深入(可能比这个答案更好)潜在的问题。我强烈推荐阅读它。
关于java - 重写 super 方法时的 ClassCastException (Comparable<T>),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63754170/