Please look at this snippet first :
public MultiThreadManager( Class<T> c) {
T[] allJobs = (T[]) Array.newInstance( c , MAX_THREAD_SIZE ) ;
for ( int i = 0 ; i < MAX_THREAD_SIZE ; i ++ ) {
allJobs[i] = (T) new Object();
service.submit( allJobs[i] );
getWaitingThreads().add( allJobs[i] );
}
}
Here is the exception :
Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to slave.JobTemplate
What I am trying to do :
The Constructor of MultiThreadManager should take a generic type ( say Job.java ) which implements Callable. Create array of all those generic data type ( Job,java ) . Initialize it so the constructor of generic data type ( Job.java ) will run and execute them in a executor service.
Please help me identify my error or please suggest a better way.
Thank You in advance
Thanks you all , but things are little more complex : Herez the other information :
public class Job extends JobTemplate<String> {...details ...}
public abstract class JobTemplate< T > implements Callable<T> {...details..}
and finally
MultiThreadManager< Job > threadManager = new MultiThreadManager< Job >( Job.class );
Again thanks :)
When you say
new Object()
, that creates a new object of class Object. Its dynamic, run-time type is Object. So the cast toT
wouldn't be logically valid, unlessT
is in factObject
.What you would need to do to create a
T
is use reflection to invoke the appropriate constructor onT
.Robin & Marko showed the source of the issue, and I have one more thing to stress out, from "Effective Java" By Joshua Bloch:
Explanation:
Covariant - means, for example, that Array of Objects is supertype of Array of Integer. Generics are invarient, means, you can't cast a
List<Integeer>
to aList<Object>
Reified - all the information that exists for arrays during compile-time is also available during run-time. Generics are implemented by erasure which means that their type constraints is enforced only during compile-time and then erased (it doesn't exist during run-time).
To sum up:
Mixing arrays with generics will most likely cause you problems - try to avoid mixing the two by using Lists instead of arrays:
You'll need more reflection, just as you need to create the array:
and surround with try-catch for all those pesky checked exceptions.
However, I would suggest using
new Callable[]
because there's no need to go into the specifics of the actual job type. You should also consider a design where reflection is unnecessary: the caller instantiates the jobs instead of passing in the class object. The current solution suffers from the restriction on the Job type to be instantiated only through the default constructor.