我编写了一个泛型类,下面是该类的构造函数.我想做这样的事情就像写在线一样
elements = (E[])new Object[size]
Run Code Online (Sandbox Code Playgroud)
因为我不知道运行时的泛型类型因此会抛出异常.
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];
}
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以解决这些问题吗?E的声明是
protected E[] elements = null;
Run Code Online (Sandbox Code Playgroud)
这就是我试图打电话的方式
Random ran = new Random();
Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));
Run Code Online (Sandbox Code Playgroud)
更新 伙计们,感谢您的帮助.我正在搞乱泛型,所以问题正在形成.以下是创建问题的所有代码 -
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();
}
Run Code Online (Sandbox Code Playgroud)
更新2:看起来,除了传递下面的答案中提到的类类型,我们无法做到这一点.
这是重现异常所需的最少代码。
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;
}
}
Run Code Online (Sandbox Code Playgroud)
Java 泛型是通过类型擦除实现的,因此在编译后,此代码转换为如下所示:
class Stack {
protected Object[] elements = new Object[1];
}
class IntStack extends Stack {
void push(Integer i) {
// throws ClassCastException
((Integer[])elements)[0] = i;
}
}
Run Code Online (Sandbox Code Playgroud)
显然 anew 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;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,当你这样做时(E[])new Object[size],这是一个谎言.对象的实际运行时类Object[],这是不是一个亚型E[]无论什么E是(除非E是Object).因此,演员在理论上是不正确的.但是,这不会立即产生任何问题,因为在这种情况下,Stack类内部会E被擦除到其上限Object.所以在Stack课堂上,我们可以使用elementsas E[],并放入E和E摆脱它,没有问题.
只有当(不正确的)的事实时发生的问题elements的类型是E[]"暴露"的类的外部,的擦除的范围之外E,到了某人具有用于混凝土类型参数一个范围E.这通常发生在有人无意中elements公开,或实现一种将其返回到外部的方法时
E[] getElements() {
return elements;
}
Run Code Online (Sandbox Code Playgroud)
然后在课堂的外面,有人有一个Stack<SomeSpecificType>,并调用这个方法,并期待一个SomeSpecificType[],这不是它得到的.
但是,你的Stack班级没有这样的方法.那你怎么"暴露" elements?答案是:elements是protected的,因此被"暴露"在子类中.在这种情况下,子类以特定类型MinMaxStack扩展,因此,它"看到" 特定类型的数组,而不是.StackEelements