[英]Java Generic object initialization
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. MultiThreadManager的构造方法应采用可实现Callable的通用类型(例如Job.java)。 Create array of all those generic data type ( Job,java ) .
创建所有那些通用数据类型(Job,java)的数组。 Initialize it so the constructor of generic data type ( Job.java ) will run and execute them in a executor service.
对其进行初始化,以便通用数据类型(Job.java)的构造函数将在执行程序服务中运行并执行它们。
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 : 谢谢大家,但是事情要复杂得多:Herez其他信息:
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 :) 再次感谢:)
You'll need more reflection, just as you need to create the array: 您将需要更多的反射,就像需要创建数组一样:
allJobs[i] = c.newInstance();
and surround with try-catch for all those pesky checked exceptions. 并用try-catch包围所有烦人的检查异常。
However, I would suggest using new Callable[]
because there's no need to go into the specifics of the actual job type. 但是,我建议使用
new Callable[]
因为没有必要讨论实际作业类型的细节。 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.
当前解决方案受困于只能通过默认构造函数实例化的Job类型的限制。
When you say new Object()
, that creates a new object of class Object. 当您说
new Object()
,将创建Object类的新对象。 Its dynamic, run-time type is Object. 它的动态运行时类型是Object。 So the cast to
T
wouldn't be logically valid, unless T
is in fact Object
. 因此,除非
T
实际上是Object
,否则对T
的强制转换在逻辑上将无效。
What you would need to do to create a T
is use reflection to invoke the appropriate constructor on T
. 创建
T
所需要做的是使用反射在T
上调用适当的构造函数。
Robin & Marko showed the source of the issue, and I have one more thing to stress out, from "Effective Java" By Joshua Bloch : Robin&Marko指出了问题的根源,我还要强调一下, Joshua Bloch撰写的“ Effective Java” :
Item 25: Prefer lists to arrays
第25条:优先选择列表而不是数组
... arrays and generics have very different type rules....数组和泛型具有非常不同的类型规则。 Arrays are covariant and reified;
数组是协变的且是精确化的; generics are invariant and erased.
泛型是不变的且已删除。 As a consequence, arrays provide runtime type safety but not compile-time type safety and vice versa for generics.
因此,对于泛型,数组提供运行时类型安全性,但不提供编译时类型安全性,反之亦然。 Generally speaking, arrays and generics don't mix well.
一般来说,数组和泛型不能很好地混合使用。 If you find yourself mixing them and getting compile-time errors or warnings, your first impulse should be to replace the arrays with lists.
如果发现自己混合使用它们并得到编译时错误或警告,则第一个冲动应该是用列表替换数组。
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 a List<Object>
泛型是不变的,这意味着您不能将
List<Integeer>
转换为List<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: 将数组与泛型混合很可能会引起您的问题-尝试通过使用列表而不是数组来避免将两者混合:
public <T> void MultiThreadManager(Class<T> c)
throws IllegalAccessException, InstantiationException {
List<T> allJobs = new ArrayList<T>(MAX_THREAD_SIZE) ;
for (int i = 0; i < MAX_THREAD_SIZE; i++) {
allJobs.add(c.newInstance());
service.submit( allJobs.get(i) );
getWaitingThreads().add( allJobs.get(i));
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.