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 должен принимать универсальный тип (скажем, Job.java), который реализует Callable. Создайте массив всех этих общих типов данных ( 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 );

Еще раз спасибо:)

3 ответа

Вам нужно больше размышлений, так же, как вам нужно создать массив:

allJobs[i] = c.newInstance();

и окружить try-catch для всех этих надоедливых проверенных исключений.

Тем не менее, я бы предложил использовать new Callable[] потому что нет необходимости вдаваться в специфику фактического типа работы. Вам также следует рассмотреть проект, в котором отражение не требуется: вызывающий объект создает экземпляры заданий, а не передает объект класса. Текущее решение страдает от ограничения на тип задания, который должен быть создан только через конструктор по умолчанию.

Когда ты сказал new Object(), что создает новый объект класса Object. Его динамический тип во время выполнения - Object. Так что актёрский состав T не будет логически обоснованным, если T на самом деле Object,

Что вам нужно сделать, чтобы создать T это использовать отражение, чтобы вызвать соответствующий конструктор на T,

Робин и Марко показали источник проблемы, и у меня есть еще одна вещь, которую стоит подчеркнуть, из "Эффективной Явы" Джошуа Блоха:

Пункт 25: Предпочитайте списки массивам
... массивы и дженерики имеют очень разные правила типов. Массивы ковариантны и ограничены; дженерики инвариантны и стерты. Как следствие, массивы обеспечивают безопасность типов во время выполнения, но не обеспечивают безопасность типов во время компиляции и наоборот для обобщенных типов. Вообще говоря, массивы и дженерики плохо сочетаются. Если вы обнаружите, что смешиваете их и получаете ошибки или предупреждения во время компиляции, ваш первый импульс должен состоять в том, чтобы заменить массивы списками.

Объяснение:

Ковариант - означает, например, что Array of Objects является супертипом Array of Integer. Дженерики неизменны, значит, вы не можете List<Integeer> к List<Object>

Reified - вся информация, которая существует для массивов во время компиляции, также доступна во время выполнения. Обобщения реализуются с помощью стирания, что означает, что их ограничения типов применяются только во время компиляции, а затем стираются (их не существует во время выполнения).

Подводя итог:
Смешивание массивов с обобщениями, скорее всего, вызовет у вас проблемы - старайтесь не смешивать их, используя списки вместо массивов:

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));
    }
}
Другие вопросы по тегам