【问题标题】:Java Generic object initializationJava 通用对象初始化
【发布时间】:2013-11-16 20:21:55
【问题描述】:

请先看看这个sn-p:

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

再次感谢:)

【问题讨论】:

    标签: java generics object-initialization


    【解决方案1】:

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

    allJobs[i] = c.newInstance();
    

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

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

    【讨论】:

    • 马克你能检查我的编辑...谢谢:)
    • 非常感谢。你的建议有帮助:)
    【解决方案2】:

    当你说new Object() 时,它创建了一个 Object 类的新对象。它的动态运行时类型是 Object。因此,T 的强制转换在逻辑上是无效的,除非 T 实际上是 Object

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

    【讨论】:

    • 谢谢罗宾。但事情有点复杂:) 剩下的就是这样:
    【解决方案3】:

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

    第 25 条:列表优于数组
    ... 数组和泛型有非常不同的类型规则。数组 是协变和具体化的;泛型是不变的和被擦除的。作为一个 结果,数组提供运行时类型安全,但不提供编译时 泛型的类型安全,反之亦然。一般来说,数组 和泛型混合不好。如果你发现自己把它们混在一起 遇到编译时错误或警告,你的第一反应应该是 用列表替换数组。

    说明:

    协变 - 例如,表示对象数组是整数数组的超类型。泛型是不变的,也就是说,您不能将 List&lt;Integeer&gt; 转换为 List&lt;Object&gt;

    Reified - 在编译时存在于arrays 的所有信息在运行时也可用。泛型由 erasure 实现,这意味着它们的类型约束仅在编译时强制执行,然后被删除(在运行时不存在)。

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

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

    【讨论】:

    • 感谢 alfasin ...我会尝试重构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-27
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多