2012-01-06 2 views
4

Поскольку я не использовал дженерики в течение некоторого времени, я довольно смущен в этом примере.Исключительное исключение указателя при работе с дженериками в java

У меня есть следующий базовый абстрактный класс:

public abstract class ExcelReader<T>{ 
    protected T type; 
    protected GenericResolver resolver; 

    public ExcelReader(){ 
     super(); 
     resolver=ResolverFactory.createResolver(type.getClass()); 
    } 
} 

теперь мой подкласс следующее:

public class POIReader<T> extends ExcelReader<T>{ 

} 
//...Implementation of methods ommited for brevity 

Сейчас в моей службы я создаю новый объект следующим образом:

ExcelReader<MessageDTO> reader=new POIReader<MessageDTO>(); 

Однако, когда конструктор ExcelReader называется атрибутом типа, имеет значение null, а в минусе ecuence бросает исключение NullPointer при создании распознавателя.

Я думаю, вы можете получить представление о том, что я пытаюсь сделать с фрагментами кода выше, и я видел примеры, используя поле атрибута для сохранения типа параметризованного класса.

Однако я очень смущен тем, почему я получаю null в атрибуте type, и как я мог его избежать. Большое спасибо.

ответ

0

Я не думаю, что вы пытаетесь использовать генерики вещи они были предназначены для использования. Дженерики являются своего рода «синтаксическим сахаром» применимым только во время компиляции как дополнительный уровень проверки кода. То, что вы, похоже, хотите достичь - исправьте меня, если я ошибаюсь, - предоставить общий тип вашему классу POIReader и затем (во время выполнения) получить доступ к объекту класса этого типа. Это верно?

, как вы могли бы использовать дженерики в вашем примере - но я не уверен, что это будет то, что вы хотите достичь - это что-то вроде этого:

public abstract class ExcelReader<T>{ 
    protected T value; 
    protected GenericResolver resolver; 

    public ExcelReader(T value) { 
     super(); 
     resolver=ResolverFactory.createResolver(type.getClass()); 
    } 
} 

public class POIReader<T> extends ExcelReader<T>{ 
    public POIReader(T value) { 
     super(value); 
    } 
} 

, а затем:

MessageDTO yourObject = ...; 
ExcelReader<MessageDTO> reader=new POIReader<MessageDTO>(yourObject); 

Таким образом, благодаря использованию дженериков компилятор не позволит передавать все, что не может быть присвоено классу MessageDTO в качестве аргумента для конструктора POIReader, но вы все равно должны назначить что-то в это поле значений, чтобы иметь возможность вызвать метод getClass(). Это связано с тем, что из-за стирания типов дженериков (неудачная обратная совместимость) генерируемые вами дженерики не доступны во время выполнения, только во время компиляции.

13

Вы звоните type.getClass(), но в этот момент type является гарантировано должно быть null. Никакой другой код не имел бы возможности установить его, так как вы ожидали его работы? Вы говорите, что вы смущены тем, почему это пустое, но вы не показали ничего, что сделало бы его ненулевым.

Я подозреваю, что вы хотите что-то вроде:

public abstract class ExcelReader<T>{ 
    protected final Class<T> type; 
    protected GenericResolver resolver; 

    public ExcelReader(Class<T> type){ 
     this.type = type; 
     resolver = ResolverFactory.createResolver(type); 
    } 
} 

Вы хотели бы ввести такой же параметр на подклассы тоже.

0

Вы точно объяснили проблему. type - null. Итак, что вам нужно делать? Сделайте это непустым. Измените конструктор следующим образом:

protected ExcelReader(T type){ 
    super(); 
    this.type = type; 
    resolver=ResolverFactory.createResolver(type.getClass()); 
} 

Теперь ваш подкласс должен отправить этот параметр, например.

public class POIReader extends ExcelReader<MessageDTO>{ 
    public POIReader() { 
     super(MessageDTO.class); 
    } 
} 

В качестве альтернативы вы можете сделать свой подкласс родовыми тоже, поэтому ответственность на отправку типа перемещается к клиенту:

public class POIReader<T> extends ExcelReader<T>{ 
    public POIReader(Class<T> type) { 
     super(type); 
    } 
} 

// and call it: 
new POIReader(MessageDTO.class);