我在Android环境中工作,并尝试了以下代码,但似乎不起作用。
如果我定义如下:
1
| String [] stockArr = {"hello", "world"}; |
它起作用了。我有什么东西不见了吗?
- 使用EDCOX1 0参见
- @Nishant你不需要铸造!String[] stockArr = stock_list.toArray(new String[0]);就足够了。
- 已经用JDK-11的更新方法给出了这个答案,在toArray(T[])中引入了一个性能相同的新API,在语法上与Stream.toArray相似。
像这样使用。
1 2 3 4 5 6 7 8 9
| List <String > stockList = new ArrayList <String >();
stockList. add("stock1");
stockList. add("stock2");
String[] stockArr = new String[stockList. size()];
stockArr = stockList. toArray(stockArr );
for(String s : stockArr )
System. out. println(s ); |
- 提供的解释,为什么在这里是事,JVM不知道如何blindly downcast [对象](The result of拷贝()[中])的字符串。让它知道你所需的对象类型是A型,你可以通个拷贝(阵列)。型可以在任何大小的数组(字符串[ 1 ]是有效的),但如果它是太小的话,它会调整它的JVM的。
- "dhackner"……在JVM不知道如何blindly downcast字符串对象[ ] [ ]"。或更多,它是精确的,不允许做的。如果它可以做,这将是违反Java的类型安全。
- stock_list.toArray(stockArr)stockArr = stock_list.toArray(stockArr)代替使用。湖stackoverflow.com 597657 9572820 / / /
- 它可能是一个有用的noobies太,你应该double, floats, ints, longs(原始类型的数组列表中),你必须使用你的阵列作为原始对象的ArrayList的含A型,例如Double, Float, Integer, Long。然后从那里你必须定义这一正常的数组的类型,如Double[] myDoubleArray = list.toArray(new Double[listOfDoubles.size()]);
- 知识@ dhackner会它使用给定的数组?只要我知道,数组不能被工具……
- "Vishal NO,它是危险的。如果你通过了A型.toArray()阵列阵列和然后你得到"不兼容的类型,在"Object[]预警的结果stockArr试图分配一个。本代码是运行在。它.toArray(stockArr);
- 一个解决的铸造。在我使用return语句return (String[]) myArrayList.toArray();I
- 你为什么要写在stockArr = stockList.toArray(stockArr);stockArr两次?
- 不要使用stockList.size()作为大小,但是0,因为在大小为0时进行了JVM优化,所以在返回之前不必用空值覆盖数组的内存,从而加速了.shipilev.net/blog/2016/arrays-willigent-ancients
- 根据Joshua Bloch在有效Java中,预先分配阵列危害性能。请改为提供零长度数组。stockList.toArray(new String[0])
- 不适用于基元类型(long[],仅适用于long[]类)
- @费里比格感谢你的链接,优秀的文章。这里的答案有点含糊,因为如果他用正确的大小填充数组,就不必返回数组,但是.size()调用使其比决定让VM分配一个新数组(至少在ArrayList上)慢。仅当静态地知道数组的大小时,用正确的大小填充数组才有意义。在这种情况下,您不应该接收返回的数组,这是多余的,只会让人感到困惑。
试试这个
- [对象] _ list.toarray obj =楼(字符串);[ ] [ ] =新的字符串stockarr obj.length;for(int i=0;i<stockarr.length;i++){stockarr〔i〕=〔i〕(字符串));}
- 为任何人想知道发生了什么在quannguyen的评论:"他是我的Object[]检索由.toArray()然后手动复制内容到一个新的String[]过每一个元素a,String铸造。这是一个坏的方法而不是你应该准时到.toArray()String[]通新
- 你不需要护照list.size(),本想创建更大的开销只是一阵列将创建临时discarded吧。我只是String[] arr = list.toArray(new String[] {});加载。安静,由于大学oneliner + 1的简单答案。
- leoholanda @,如果阵列中提供的参数列表不同的是,相同的数组,如果尺寸不合适,它allocates数组本身,你在你的案例,最终创建一个虚拟阵列(of size为0)。
- 注意,toArray(new String[0])实际上是更快的比toArray(new String[list.size()]):stackoverflow.com /问题/ 4042434 / & hellip;
- 一个让reverted编辑评论有关。其他答案new String[0]版本已经报告。
正在发生的是,stock_list.toArray()创建的是Object[],而不是String[],因此类型转换失败1。
正确的代码是:
1
| String [] stockArr = stockList. toArray(new String[stockList. size()]); |
甚至
有关更多详细信息,请参阅JavaDocs了解List.toArray的两个重载。
后一个版本使用零长度数组来确定结果数组的类型。(令人惊讶的是,这样做要比预先分配…至少,对于最近的Java版本来说。详情请参见https://stackoverflow.com/a/4042464/139985。)
从技术角度来看,这种API行为/设计的原因是,List.toArray()方法的实现没有关于在运行时是什么的信息。它只知道原始元素类型是Object。相反,在另一种情况下,array参数给出了数组的基类型。(如果提供的数组足够大以容纳列表元素,则使用它。否则,将分配一个类型相同、大小较大的新数组,并作为结果返回。)
1——在Java中,EDCOX1×1 }不是与EDCOX1 2Ω赋值兼容的。如果是,那么你可以这样做:
1 2 3
| Object[] objects = new Object[]{new Cat ("fluffy")};
Dog [] dogs = (Dog []) objects ;
Dog d = dogs [0]; // Huh??? |
这显然是胡说八道,这就是数组类型一般不兼容赋值的原因。
- 这为什么不工作?字符串[] GS =(字符串[])stocklist.toarray();
- 这是解释@ Ashwin -在第一线的答案。如果你想legalistic的"为什么",因为这是它是如何toArray()是指定由javadoc。
- 我想知道为什么不接受这一答案?这里是信息的唯一的根的问题的答案,其余的只是解决方案。
- "我想这是最pshemo upvoters只是想理解为什么没有解决方案。
- "我认为大多数人pshemo Don’t看过去的答案,如果它包含公认的工作解决方案。本案例中,有高度upvoted评论,甚至不提供解释。我很高兴我scrolled唐氏虽然。
- 这不与原始类型。
- 如果你的意思是,它转换成一个int[]a List担忧……这是正确的。它把它在Integer[]。
Java 8中的另一种选择:
- 仅供参考,intellij建议将其更改为list.toArray(new String[0])。我不知道为什么。
- @你的项目的目标语言版本是什么?
- @我相信是惠尔温8号。
我可以看到许多答案显示如何解决问题,但只有斯蒂芬的答案试图解释问题发生的原因,因此我将尝试在此主题上添加更多内容。这是一个可能的原因,为什么EDCOX1 0不改变为EDCOX1,1,泛型软件引入Java。好的。为什么String[] stockArr = (String[]) stock_list.toArray();不起作用?在爪哇中,仅在编译时存在泛型类型。在运行时,有关泛型类型的信息(如在您的情况下,被删除并替换为Object类型(查看类型擦除)。这就是为什么在运行时,toArray()不知道要使用什么精确类型来创建新数组,所以它使用Object作为最安全的类型,因为每个类都扩展对象,这样它就可以安全地存储任何类的实例。好的。现在的问题是,您不能将Object[]的实例强制转换为String[]。
为什么?看看这个例子(假设class B extends A):好的。
1 2 3
| //B extends A
A a = new A();
B b = (B)a; |
虽然这样的代码会编译,但在运行时我们会看到抛出的ClassCastException,因为引用a所持有的实例实际上不是B类型(或其子类型)。为什么会出现此问题(为什么需要强制转换此异常)?其中一个原因是,B可能有a不具备的新方法/字段,因此,即使持有的实例没有(不支持)这些新成员,也有可能有人试图通过B引用来使用这些新成员。换句话说,我们最终可能会尝试使用不存在的数据,这可能会导致许多问题。因此,为了防止这种情况,JVM抛出异常,并停止进一步的潜在危险代码。好的。
你现在可以问,"那我们为什么不早点停下来呢?为什么涉及这种类型转换的代码甚至是可编译的?编译器不应该停止它吗?".答案是:不,因为编译器无法确定a引用所持有的实例的实际类型,并且有可能持有支持B引用接口的B类实例。看看这个例子:好的。
1 2 3 4
| A a = new B();
// ^------ Here reference"a" holds instance of type B
B b = (B)a; // so now casting is safe, now JVM is sure that `b` reference can
// safely access all members of B class |
现在我们回到你的数组。正如您在问题中看到的,我们不能将Object[]数组的实例强制转换为更精确的String[]类型好的。
这里的问题有点不同。现在,我们确信String[]数组不会有其他字段或方法,因为每个数组只支持:好的。
- []运算符,
- length备案,
- 从对象父类型继承的方法,
所以这不是数组接口,这使得它不可能。问题是,Strings旁边的Object[]数组可以存储任何对象(例如Integers),所以有一天我们可能会在没有Integer的情况下尝试调用strArray[i].substring(1,3)这样的方法。好的。
因此,为了确保这种情况永远不会发生,在Java数组引用中只能保存好的。
- 与引用类型相同的数组实例(引用String[] strArr可以容纳String[])
- 子类型数组的实例(Object[]可以容纳String[],因为String是Object的子类型,
但不能举行好的。
- 引用的数组类型的父类型数组(String[]不能容纳Object[])
- 与引用中的类型无关的类型数组(Integer[]不能容纳String[])
换言之,像这样的事情是可以的好的。
1 2 3 4
| Object[] arr = new String[] {"ab", "cd" }; //OK - because
// ^^^^^^^^ `arr` holds array of subtype of Object (String)
String[] arr2 = (String[]) arr ; //OK - `arr2` reference will hold same array of same type as
// reference |
您可以说,解决此问题的一种方法是在运行时在所有列表元素之间找到最常见的类型,并创建该类型的数组,但在列表的所有元素都是从通用类型派生的一种类型的情况下,这不起作用。看一看好的。
1 2 3 4
| //B extends A
List<A> elements = new ArrayList<A>();
elements.add(new B());
elements.add(new B()); |
现在最常见的是B,不是a,所以toArray()。好的。
1
| A[] arr = elements.toArray(); |
将返回B类new B[]的数组。这个数组的问题是,虽然编译器允许您通过向它添加new A()元素来编辑它的内容,但您将得到ArrayStoreException,因为B[]数组只能保存类B或其子类的元素,以确保所有元素都支持B的接口,但a的实例除外。可能没有B的所有方法/字段。所以这个解决方案并不完美。好的。
此问题的最佳解决方案是通过将此类型作为方法参数(如好的。
或好的。
1
| String[] arr = list. toArray(new String[0]); //if size of array is smaller then list it will be automatically adjusted. |
好啊。
- 这都是正确的,但问题的根本原因比一般类型更深层/更古老。自从引入收集框架以来,toArray方法的行为就是这样的。它比普通的早了很多年。(你可以说,仿制药并没有解决这个问题…)
- @是的,我只关注泛型问题,忘记了这个工具并不总是集合框架的一部分。我将尝试重写此答案以包含您的信息,但不能这样做。如果你有时间,可以随意编辑它。如果你认为我不属于这个问题,也可以投反对票。
正确的方法是:
1
| String[] stockArr = stock_list. toArray(new String[stock_list. size()]); |
我想补充一下这里的其他好答案,并解释一下如何使用javadocs来回答您的问题。
这里是用于toArray()的javadoc(无参数)。如您所见,此方法返回一个Object[]而不是String[],它是列表运行时类型的数组:
public Object[] toArray()
Returns an array containing all of the
elements in this collection. If the collection makes any guarantees as
to what order its elements are returned by its iterator, this method
must return the elements in the same order. The returned array will be
"safe" in that no references to it are maintained by the collection.
(In other words, this method must allocate a new array even if the
collection is backed by an Array). The caller is thus free to modify
the returned array.
不过,在这个方法的正下方是用于toArray(T[] a)的javadoc。如您所见,此方法返回一个T[],其中T是您传入的数组类型。起初,这看起来像是您在寻找的,但不清楚为什么要传入一个数组(您是在添加数组,将其仅用于类型等)。文档清楚地表明,传递数组的目的本质上是定义要返回的数组类型(这正是您的用例):
public T[] toArray(T[] a)
Returns an array containing all of the
elements in this collection; the runtime type of the returned array is
that of the specified array. If the collection fits in the specified
array, it is returned therein. Otherwise, a new array is allocated
with the runtime type of the specified array and the size of this
collection. If the collection fits in the specified array with room to
spare (i.e., the array has more elements than the collection), the
element in the array immediately following the end of the collection
is set to null. This is useful in determining the length of the
collection only if the caller knows that the collection does not
contain any null elements.)
If this collection makes any guarantees as to what order its elements
are returned by its iterator, this method must return the elements in
the same order.
This implementation checks if the array is large enough to contain the
collection; if not, it allocates a new array of the correct size and
type (using reflection). Then, it iterates over the collection,
storing each object reference in the next consecutive element of the
array, starting with element 0. If the array is larger than the
collection, a null is stored in the first location after the end of
the collection.
当然,要真正理解这两种方法之间的区别,需要了解泛型(如其他答案中所述)。然而,如果你先去javadocs,你通常会找到你的答案,然后自己去看看你还需要学习什么(如果你真的这样做的话)。
另外,请注意,在这里阅读javadocs有助于理解传入数组的结构。虽然这实际上并不重要,但您不应像这样传递空数组:
因为,从文档中,这个实现检查数组是否足够大以包含集合;否则,它将分配一个大小和类型正确的新数组(使用反射)。当您可以轻松地传递大小时,在创建新数组时不需要额外的开销。
通常情况下,javadocs为您提供了丰富的信息和方向。
嘿,等一下,反射是什么?
- object[]obj=stock_list.toarray();
- @你在说什么?你想说什么?
- toArray(new String[0])更快:shipilev.net/blog/2016/arrays-willight-ancients