我编写了一个泛型类,下面是该类的构造函数。我想做这样的事情,如行
elements = (E[])new Object[size]
因为我不知道运行时的泛型类型,所以会抛出异常。
public class Stack<E> implements IStack<E> {
protected E[] elements = null;
protected int top = -1;
protected int size= 0;
private static final int DEFAULT_CAPACITY = 10;
public Stack(){
this(DEFAULT_CAPACITY);
}
public Stack(int size){
if(size <0){
throw new IllegalArgumentException("Initial capacity cannot be negative or zero");
}
ArrayList<Integer> ar = new ArrayList<Integer>();
elements = (E[])new Object[size];
}
}
有没有办法解决这些问题? E的声明是
protected E[] elements = null;
这就是我试图打电话的方式
Random ran = new Random();
Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));
更新 伙计们,谢谢你的帮助。我正在搞乱泛型,所以问题正在形成。以下是创建问题的所有代码 -
public class StackMain {
public static void main(String[] args) {
MinMaxStack minMaxStack = new MinMaxStack();
Random ran = new Random();
for (int k = 0; k < 10; k++) {
minMaxStack.push(ran.nextInt(100));
}
System.out.println(minMaxStack);
}
}
public class MinMaxStack extends Stack<Integer> implements IMinMaxStack<Integer>{
private int min;
private int max;
/*
* Approach 1:
* For push method we can push and update the minimum/maximum value
* For pop method we will be traversing whole stack to find out the new minimum/maximum
*
*/
@Override
public void push(Integer element){
if(isEmpty()){
this.min = element;
this.max = element;
elements[top+1] = element;
size++;
}else{
if(element < min){
min = element;
}
if(element > max){
max = element;
}
elements[top+1] = element;
size++;
}
}
}
public class Stack<E> implements IStack<E> {
protected E[] elements = null;
protected int top = -1;
protected int size= 0;
private static final int DEFAULT_CAPACITY = 10;
public Stack(){
this(DEFAULT_CAPACITY);
}
public Stack(int size){
if(size <0){
throw new IllegalArgumentException("Initial capacity cannot be negative or zero");
}
elements = (E[])new Object[size];
}
public void push(E element) {
ensureCapacity();
elements[top+1] = element;
size++;
}
}
public interface IStack<E> {
public void push(E element );
}
public interface IMinMaxStack<E> extends IStack<E> {
public int min();
public int max();
}
更新2 : 似乎除了传递下面答案中提到的类类型之外,我们无法做到这一点。
答案 0 :(得分:5)
基本上,当你做(E[])new Object[size]
时,这是一个谎言。对象的实际运行时类为Object[]
,对于E[]
来说,它不是E
的子类型(除非E
是Object
)。因此,演员在理论上是不正确的。但是,这不会立即产生任何问题,因为在Stack
类中,E
被删除到其上限,在本例中为Object
。因此,在Stack
类中,我们可以将elements
用作E[]
,并将E
放入其中并从中获取E
,没有任何问题。
仅当elements
类型E[]
被“暴露”到类的外部(不正确)时才会出现问题,超出E
的擦除范围,进入某人有E
具体类型参数的范围。这通常发生在有人无意中使elements
公开,或实现一种将其返回到外部的方法时
E[] getElements() {
return elements;
}
然后在课堂外,有人有Stack<SomeSpecificType>
,并调用此方法,并期望SomeSpecificType[]
,而不是它。
但是,您的Stack
类没有这样的方法。那你怎么“暴露”elements
?答案是elements
是protected
,因此“暴露”到子类。在这种情况下,子类MinMaxStack
使用Stack
的特定类型扩展E
,因此,它“看到”elements
作为特定类型的数组,它不是。
答案 1 :(得分:4)
以下是重现异常所需的最小代码。
class Stack<E> {
protected E[] elements = (E[])new Object[1];
}
class IntStack extends Stack<Integer> {
void push(Integer i) {
// subtly accessing elements as Integer[] which it's not
elements[0] = i;
}
}
Java泛型使用type erasure实现,因此在编译之后,此代码转换为以下内容:
class Stack {
protected Object[] elements = new Object[1];
}
class IntStack extends Stack {
void push(Integer i) {
// throws ClassCastException
((Integer[])elements)[0] = i;
}
}
显然,new Object[]
不是Integer[]
。注意演员如何移动到你没有明确表达的地方。这就是(E[])new Object[size]
是未经检查的广告并显示警告的原因。
相反,您应该使用Object[]
并仅在需要将元素返回到外部世界时执行未经检查的强制转换。
class Stack<E> {
private Object[] elements;
private int size;
Stack(int len) {
elements = new Object[len];
}
void push(E e) {
elements[size] = e;
size++;
}
E pop() {
@SuppressWarnings("unchecked");
E e = (E)elements[size - 1];
size--;
return e;
}
}
答案 2 :(得分:3)
我认为通常的方法是将Class
传递给构造函数,并使用Array.newInstance(Class<?>, int...)
之类的
public Stack(Class<E> cls, int size){
if(size <0){
throw new IllegalArgumentException("Initial capacity cannot be "
+ "negative or zero");
}
elements = (E[]) Array.newInstance(cls, size);
}
修改强>
在您的更新中, 请勿使用raw-types。使用Java 7及更高版本,您可以使用diamond operator <>
之类的
Stack<Integer> st = new Stack<>();
st.push(ran.nextInt(100));
使用早期版本,您可以指定类似
的泛型类型Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));
答案 3 :(得分:1)
现在很清楚了。您正在尝试创建没有通用类型的Stack
。请考虑使用Stack<Integer> st = new Stack<>();
。
答案 4 :(得分:1)
以下是如何修复它,你不应该(T[]) new Object[DEFAULT_CAPACITY];
代替抽象应该存在例如(T[]) new Comparable[DEFAULT_CAPACITY];
public class ArrayStack<T extends Comparable<? super T>> implements Stack<T> {
private final int DEFAULT_CAPACITY = 50;
private int top;
private T[] elements;
@SuppressWarnings("unchecked")
public ArrayStack() {
this.elements = (T[]) new Comparable[DEFAULT_CAPACITY];
this.top = 0;
}
}