ClassCastException on Array content cast

R

RVic

I have an ArrayList which I populate with DmFieldInfo objects (I can
confirm this is working correctly):

ArrayList<DmFieldInfo> arrayList = new ArrayList<DmFieldInfo>();

I want to now move tis ArrayList over to an Array of DmFieldInfo
objects, so:

DmFieldInfo dmFieldInfos [] = new DmFieldInfo[arrayList.size()];
dmFieldInfos = (DmFieldInfo[]) arrayList.toArray();

And on this last line I get the error message at runtime that:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
[DmFieldInfo;

How else do I convert this ArrayList of a particular object type to an
Array of that object type? Thanks.
 
R

RVic

Answered my own q -- in case anyone hits this in the future on a
search, should be:

arrayList.toArray(dmFieldInfos); //provided dmFieldInfos is th correct
length

instead of :
e
dmFieldInfos = (DmFieldInfo[]) arrayList.toArray();
 
L

Lew

RVic said:
Answered my own q [sic] -- in case anyone hits this in the future on a
search, should be:

Given that the two forms of toArray() are document right adjacent to each
other in the Javadocs, it shouldn't be hard to find one given the other.
arrayList.toArray(dmFieldInfos); //provided dmFieldInfos is th correct
length

dmFieldInfos can be any length. It is common to see this idiom as:

DmFieldInfo [] dmFieldInfos = arrayList.toArray( new DmFieldInfo [0] );

This usage is documented in the Javadocs for 'toArray( T [] )'.
instead of :
e
dmFieldInfos = (DmFieldInfo[]) arrayList.toArray();

This form uses the version that returns Object []. In your original example,
you show an attempt to assign two different arrays to the variable
dmFieldInfos, wasting the construction of the first empty array.

I realize that 'arrayList' is only for expository purposes, or else it would
be a pretty bad variable name. Consider declaring variables as the interface
type rather than a specific concrete type.
 
B

Bill McCleary

Lew said:
RVic said:
Answered my own q [sic] -- in case anyone hits this in the future on a
search, should be:

Given that the two forms of toArray() are document right adjacent to
each other in the Javadocs, it shouldn't be hard to find one given the
other.
arrayList.toArray(dmFieldInfos); //provided dmFieldInfos is th correct
length

dmFieldInfos can be any length. It is common to see this idiom as:

DmFieldInfo [] dmFieldInfos = arrayList.toArray( new DmFieldInfo [0] );

How cheap is the creation and discarding of the zero-length array here?
My guess would be decently cheap with a modern GC and especially if,
after using it for type inference, the compiler sees that it's never
used and optimizes it away. (If not javac, the JIT.)
 
L

Lew

Lew said:
DmFieldInfo [] dmFieldInfos = arrayList.toArray( new DmFieldInfo [0] );

Bill said:
How cheap is the creation and discarding of the zero-length array here?
My guess would be decently cheap with a modern GC and especially if,
after using it for type inference, the compiler sees that it's never
used and optimizes it away. (If not javac, the JIT.)

If one wants:

/** Array type token. */
private static final DmFieldInfo [] LDMFI = new DmFieldInfo [0];
...
{...
DmFieldInfo [] dmFieldInfos = dmfiBunch.toArray( LDMFI );
...}

Never mind whether it optimizes - this idiom self-documents use of the array
type token as such, without distraction by details over 'new'. There is no
algorithmic need to create a new immutable token each time. So algorithmic
and self-documentation principles both support use of the immutable empty
array as a named static constant.
 
A

Arne Vajhøj

Bill said:
Lew said:
RVic said:
Answered my own q [sic] -- in case anyone hits this in the future on a
search, should be:

Given that the two forms of toArray() are document right adjacent to
each other in the Javadocs, it shouldn't be hard to find one given the
other.
arrayList.toArray(dmFieldInfos); //provided dmFieldInfos is th correct
length

dmFieldInfos can be any length. It is common to see this idiom as:

DmFieldInfo [] dmFieldInfos = arrayList.toArray( new DmFieldInfo [0] );

How cheap is the creation and discarding of the zero-length array here?
My guess would be decently cheap with a modern GC

Allocation is cheap and GC of newly allocated object should be
cheap as well.
and especially if,
after using it for type inference,

It is not really type inference.
the compiler sees that it's never
used and optimizes it away. (If not javac, the JIT.)

Javac: no, JIT: possible, but it would require a damn good optimizer.

Arne
 
A

Arne Vajhøj

Thomas said:
As a general rule, there is no problem of performance until duly
measured,
Yep.

> and performance issues begin with algorithmics (canonical
> example is the use of a O(n2) sorting algorithm instead of O(n log n)).
One may assume that allocation and GC-ing of an object has a cost which
rises with the object size;

Really?

I would expect both allocation and GC cost to be independent of object
size.

And only moving around as part of memory defragmentation to depend
on object size.
thus, a zero-length array does not induce
algorithmic performance issue.

I am not disagreeing, but I really can't see the importance.
Hence, until further notice, it is cheap. One may prefer the use of a
static template (a zero-length array allocated once and for all) for
esthetic reasons, though.

It is an option in the very unlikely case that allocation and GC of
empty array indeed is a performance problem.
However:


I find it rather improbable, because ArrayList.toArray() will use the
provided array, fill it and return it, if it has the proper size -- and
a zero-length array is big enough if the list is empty. The JIT compiler
would require some pretty heavy context information to optimize away the
allocation.

Agree.

Arne
 
T

Tom Anderson

Lew said:
RVic said:
Answered my own q [sic] -- in case anyone hits this in the future on a
search, should be:

Given that the two forms of toArray() are document right adjacent to each
other in the Javadocs, it shouldn't be hard to find one given the other.
arrayList.toArray(dmFieldInfos); //provided dmFieldInfos is th correct
length

dmFieldInfos can be any length. It is common to see this idiom as:

DmFieldInfo [] dmFieldInfos = arrayList.toArray( new DmFieldInfo [0] );

How cheap is the creation and discarding of the zero-length array here?
My guess would be decently cheap with a modern

The birth and death of the size-zero array will be cheap. The reflection
needed to determine its element type and create a matching right-sized
array might not be. I tend to spend the extra characters on creating a
correctly-sized array here just in case.
GC and especially if, after using it for type inference, the compiler
sees that it's never used and optimizes it away.

If the compiler can do that, then yes, the cost will be negligible. That
strikes me as a pretty impressive thing to do, though.
(If not javac, the JIT.)

Definitely not javac.

tom
 
T

Tom Anderson

Really?

I would expect both allocation and GC cost to be independent of object
size.

In addition to what Thomas wrote about the effect on GC intervals,
remember that an array has to be filled with nulls (or whatever) on
allocation. That has to be O(n), doesn't it?

tom
 
A

Arne Vajhøj

Thomas said:
Roughly speaking, GC passes are triggered based on allocation rate. If
you allocate bigger objects, then you trigger more GC passes, thus
increasing cost.

Not obvious. It will run more frequently, but it will have fewer
objects to GC.
Moreover, in many GC designs, cost of a GC pass
increases with the size of reachable objects; heuristically, many
objects are short-lived enough to become unreachable before the next GC
pass. By allocating bigger objects, you make GC run more often, which
increases the probability that a given object is still reachable at the
time the GC runs.

True.

[long explanation of common GC strategies omitted]
Thus, I stand my ground: all other things being equal, allocating a
bigger object, even a very short-lived object, increases costs related
to memory allocation and management.

I still do not see it as that obvious.

But a little bit of experimentation seems to indicate that
you are right.

A primitive test shows O(1) for 1-30 bytes and O(N) for >30 bytes.

Arne
 
A

Arne Vajhøj

Tom said:
In addition to what Thomas wrote about the effect on GC intervals,
remember that an array has to be filled with nulls (or whatever) on
allocation. That has to be O(n), doesn't it?

If Java has to do it when allocating: yes. If it can use the OS
and HW to zero fill on demand: maybe.

Arne
 
L

Lew

According to Arne Vajhøj:
Not obvious. It will run more frequently, but it will have fewer
objects to GC.

Less obvious still, since GC is proportionate to the number of live objects,
at least in the young generation, and there's no reason to expect that to
correlate to object size. So if you trigger many, many young-generation GC
passes, but few to no young-generation objects are alive, then GC passes will
be quite fast indeed and object size will be a barely noticeable influence.

If you follow an idiom of allocating very short-lived objects very frequently,
your young-generation passes might be somewhat frequent but they might not
total much time at all, and their brevity will minimize interruptions of the
primary activities.
 
R

Roedy Green

see http://mindprod.com/jgloss/arraylist.html for how to do that.
Because of type erasure, it needs a template array of the correct type
passed in as a parameter.

This is the pons asinorum of Java, one of the major gotchas,
understanding the difference between:

Object[] that just happen to contain only Frog objects and
Frog[].

To help you over it see:


http://mindprod.com/jgloss/array.html#ARRAYSTOREEXCEPTION

http://mindprod.com/jgloss/runerrormessages.html#CLASSCASTEXCEPTION
--
Roedy Green Canadian Mind Products
http://mindprod.com

"We must be very careful when we give advice to younger people: sometimes
they follow it!"
~ Edsger Wybe Dijkstra, born: 1930-05-11 died: 2002-08-06 at age: 72
 
E

Eric Sosman

Roedy said:
dmFieldInfos = (DmFieldInfo[]) arrayList.toArray();

see http://mindprod.com/jgloss/arraylist.html for how to do that.
Because of type erasure, it needs a template array of the correct type
passed in as a parameter.

A minor nit: It's got nothing to do with type erasure.
Rather, it's about describing what kind of array you want:
An Object[] or a Thing[] or a Cloneable[] or whatever. The
fact that you've got a List<Double> doesn't prove that you
want to get a Double[] from it; you might need a Number[]
instead.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,717
Messages
2,569,382
Members
44,704
Latest member
FawnBernay

Latest Threads

Top