java Ljava.lang.Object; 不能转换为 [Ljava.lang.Integer
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27591061/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer
提问by Avneesh
I have written a generic class and below is the constructor of the class. I want to do something like this as written in line
我写了一个泛型类,下面是该类的构造函数。我想做这样的事情
elements = (E[])new Object[size]
Because I do not know the generic type on the run time therefore it will throw an exception.
因为我不知道运行时的泛型类型,所以它会抛出异常。
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];
}
}
Is there any way to solve such problems? The declaration of E is
有没有办法解决此类问题?E 的声明是
protected E[] elements = null;
This is how I am trying to call
这就是我试图打电话的方式
Random ran = new Random();
Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));
UpdateGuys, Thanks for the help. I was messing around with generics so the problem was being created. Here is all the code which created the problem -
更新伙计们,感谢您的帮助。我在搞泛型,所以问题就产生了。这是造成问题的所有代码 -
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();
}
Update 2: Seems, other than passing the class type as mentioned in an answer below, there is no way we can do this.
更新 2:似乎,除了传递下面答案中提到的类类型之外,我们无法做到这一点。
回答by newacct
Basically, when you do (E[])new Object[size]
, it is a lie. The object's actual runtime class is Object[]
, which is not a subtype of E[]
for whatever E
is (unless E
is Object
). So the cast is, theoretically, incorrect. However, this does not create any immediate problems because inside the Stack
class, E
is erased to its upper bound, in this case Object
. So inside the Stack
class, we can use elements
as E[]
, and put E
in and get E
out of it, with no problem.
基本上,当你这样做时(E[])new Object[size]
,这是一个谎言。对象的实际运行时类是Object[]
,它不是E[]
任何东西的子类型E
(除非E
是Object
)。因此,从理论上讲,演员阵容是不正确的。但是,这不会立即产生任何问题,因为在Stack
类内部,E
被擦除到其上限,在本例中为Object
。所以在Stack
类内部,我们可以使用elements
as E[]
,放入E
和E
退出它,没有问题。
A problem only occurs when the (incorrect) fact that elements
is type E[]
is "exposed" to the outside of the class, outside of the scope of the erasure of E
, into a scope where someone has a concrete type argument for E
. This usually happens when someone inadvertently makes elements
public, or implements a method that returns it to the outside like
只有当(不正确的)的事实时发生的问题elements
的类型是E[]
“暴露”的类,的擦除的范围之外的外侧E
,到了某人具有用于混凝土类型参数一个范围E
。这通常发生在某人无意中elements
公开或实现将其返回给外部的方法时,例如
E[] getElements() {
return elements;
}
Then on the outside of the class, someone has a Stack<SomeSpecificType>
, and call this method, and expect a SomeSpecificType[]
, which is not what it gets.
然后在类的外面,有人有一个Stack<SomeSpecificType>
, 并调用这个方法,并期望得到一个SomeSpecificType[]
,这不是它得到的。
However, your Stack
class does not have such a method. So how are you "exposing" elements
? The answer is that elements
is protected
, and is therefore "exposed" to subclasses. In this case, the subclass, MinMaxStack
, extends Stack
with a specific type for E
, therefore, it "sees" elements
as a specific type of array, which it is not.
但是,您的Stack
类没有这样的方法。那么你是如何“暴露”的elements
呢?答案是:elements
是protected
的,因此被“暴露”在子类中。在这种情况下,子类以特定类型 forMinMaxStack
扩展,因此,它“将”视为特定类型的数组,而事实并非如此。Stack
E
elements
回答by Radiodef
Here is the most-minimal code necessary to reproduce your exception.
这是重现异常所需的最少代码。
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 generics are implemented with type erasureso after compilation, this code translates to something like this:
Java 泛型是通过类型擦除实现的,因此在编译后,此代码转换为如下所示:
class Stack {
protected Object[] elements = new Object[1];
}
class IntStack extends Stack {
void push(Integer i) {
// throws ClassCastException
((Integer[])elements)[0] = i;
}
}
Clearly a new Object[]
is not an Integer[]
. Notice how the cast gets moved to somewhere you did not explicitly put it. This is why (E[])new Object[size]
was an unchecked castand displayed a warning.
显然 anew Object[]
不是Integer[]
。请注意演员如何移动到您没有明确放置的地方。这就是为什么(E[])new Object[size]
是一个未经检查的铸造和显示警告信息。
Instead, you should use Object[]
and perform the unchecked cast only when you need to return an element to the outside world.
相反,您应该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;
}
}
回答by Elliott Frisch
I believe the usual way is to pass the Class
into the constructor, and use Array.newInstance(Class<?>, int...)
like
我相信通常的方法是将 传递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);
}
Edit
编辑
From your update, pleasedon't use raw-types. With Java 7 and above you can use the diamond operator <>
like
从您的更新中,请不要使用raw-types。使用 Java 7 及更高版本,您可以使用菱形运算符,<>
例如
Stack<Integer> st = new Stack<>();
st.push(ran.nextInt(100));
With earlier versions you specify the generic type like
对于早期版本,您可以指定泛型类型,例如
Stack<Integer> st = new Stack<Integer>();
st.push(ran.nextInt(100));
回答by Everv0id
It's clear now. You're trying to create your Stack
without generic type. Consider Stack<Integer> st = new Stack<>();
instead.
现在很清楚了。您正在尝试创建Stack
没有泛型的类型。考虑一下Stack<Integer> st = new Stack<>();
。
回答by craftsmannadeem
Here is how you would fix it, you should not ever do (T[]) new Object[DEFAULT_CAPACITY];
instead an abstraction should be there for example (T[]) new Comparable[DEFAULT_CAPACITY];
这是您将如何修复它,例如,您不应该这样做,(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;
}
}