Java 泛型对象初始化



请先看看这个片段:

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] );
    }           
}

这是例外:

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to slave.JobTemplate

我想做什么:

MultiThreadManager的构造函数应该采用一个实现Callable的泛型类型(比如Job.java)。创建所有这些通用数据类型(Job,java)的数组。初始化它,以便泛型数据类型 ( Job.java 的构造函数将在执行器服务中运行和执行它们。

请帮助我识别我的错误或提出更好的方法。

提前谢谢你

谢谢大家,但事情有点复杂:赫兹其他信息:

public class Job extends JobTemplate<String> {...details ...}
public abstract class JobTemplate< T > implements Callable<T> {...details..}

最后

MultiThreadManager< Job > threadManager = new MultiThreadManager< Job >( Job.class );

再次感谢:)

您将需要更多的反射,就像您需要创建数组一样:

allJobs[i] = c.newInstance();

并用 try-catch 包围所有这些讨厌的检查异常。

但是,我建议使用new Callable[]因为没有必要深入了解实际工作类型的细节。您还应该考虑不需要反射的设计:调用方实例化作业而不是传入类对象。当前解决方案受到只能通过默认构造函数实例化的 Job 类型的限制。

当你说new Object()时,会创建一个类对象的新对象。其动态运行时类型为"对象"。因此,T的演员阵容在逻辑上是无效的,除非T实际上是Object

创建T需要做的是使用反射在T上调用适当的构造函数。

Robin & Marko 展示了问题的根源,我还有一件事要强调,来自 Joshua Bloch 的"Effective Java"

第 25 项:首选列表而不是数组
... 数组和泛型具有非常不同的类型规则。阵 列 是协变和统一的;泛型是不变的,并且会被擦除。作为一个 因此,数组提供运行时类型安全,但不提供编译时安全性 泛型的类型安全,反之亦然。一般来说,数组 泛型不能很好地混合。如果您发现自己混合了它们并且 收到编译时错误或警告,您的第一个冲动应该是 将数组替换为列表。

解释:

协变 - 表示,例如,对象数组是整数数组的超类型。泛型是不变的,这意味着您不能将List<Integeer>转换为List<Object>

已化 - 编译时数组存在的所有信息在运行时也可用。泛型是通过擦除实现的,这意味着它们的类型约束仅在编译时强制执行,然后被擦除(它在运行时不存在)。

总结一下
将数组与泛型混合使用很可能会给您带来问题 - 尽量避免使用 Lists 而不是数组来混合两者:

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));
    }
}

相关内容

  • 没有找到相关文章

最新更新