简体   繁体   English

Java通用对象初始化

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM