Краткий ответ
Дженерики здесь не тот инструмент.Вы можете сделать приведение явным:
public class CompanyPDFGenerator implements EntityPDFGenerator
{
public void generate(Entity entity)
{
if (! (entity instanceof Company)) {
throw new IllegalArgumentException("CompanyPDFGenerator works with Company object. You provided " + (entity == null ? "null" : entity.getClass().getName()));
}
Company company = (Company) entity;
System.out.println(company);
// create Company related PDF
}
}
Или вы можете определить какую-то структуру данных в классе сущностей и использовать только такую в принтере:
public abstract class Entity
{
int id;
public abstract EntityPdfData getPdfData();
}
// ...
public class CompanyPDFGenerator implements EntityPDFGenerator
{
public void generate(Entity entity)
{
EntityPdfData entityPdfData = entity.getPdfData();
// create Company related PDF
}
}
Длинный ответ
Обобщения полезны, если вы знаете типы во время компиляции.Т.е. если вы можете записать в свою программу этот фактический тип.Для списков это выглядит так просто:
// now you know at compile time that you need a list of integers
List<Integer> list = new ArrayList<>();
В вашем примере вы не знаете, что:
public void generate(Entity entity)
{
// either Article or Company can come it. It's a general method
EntityPDFGenerator pdfGenerator = getConcretePDFGenerator(entity);
pdfGenerator.generate(entity);
}
Предположим, вы хотите добавить тип к EntityPDFGenerator
, например так:
public static interface EntityPDFGenerator<T extends Entity>
{
void generate(T entity);
}
public static class ArticlePDFGenerator implements EntityPDFGenerator<Article>
{
public void generate(Article entity)
{
Article article = (Article) entity;
// create Article related PDF from entity
}
}
public static class CompanyPDFGenerator implements EntityPDFGenerator<Company>
{
public void generate(Company entity)
{
Company company = (Company) entity;
// create Company related PDF
}
}
Это выглядит красиво.Однако получить правильный генератор будет сложно.Обобщения Java инвариантны.Даже ArrayList<Integer>
не является подклассом ArrayList<Number>
.Таким образом, ArticlePdfGenerator
не является подклассом EntityPDFGenerator<T extends Entity>
.Т.е. это не скомпилируется:
<T extends Entity> EntityPDFGenerator<T> getConcretePDFGenerator(T entity, Class<T> classToken)
{
if(entity instanceof Article){
return new ArticlePDFGenerator();
}else{
return new CompanyPDFGenerator();
}
}