2013-12-01 3 views
0

Я реализую неизменяемый композит с использованием шаблона строителя и абстрактного базового класса как для элементов, так и для строителей. Чтобы уменьшить необходимость в кастинге и получить код для элементов как можно более краткими, я создаю базовые классы, используя дженерики. Я получаю одно предупреждение, которое я не понимаю. Пожалуйста, объясните, почему показано предупреждение и как я могу избавиться от него (без использования @SuppressWarnings («unchecked»))?Как избавиться от предупреждения типа «Тип безопасности» для универсального строителя?

Вот соответствующие части моего кода:

abstract public class JElement<J extends JElement<J>> { 
    abstract protected <B extends AbstractBuilder<J, B>> B newBuilder(); 

    abstract public static class AbstractBuilder<J extends JElement<J>, B extends AbstractBuilder<J, B>> { 

     public AbstractBuilder() { 
     } 

     abstract public J build(); 
    } 
} 

public class JClass extends JElement<JClass> { 
    JClass(Builder builder) { 
    } 

    @Override 
    protected Builder newBuilder() { 
     return new Builder(this); 
    } 

    public static class Builder extends JElement.AbstractBuilder<JClass, Builder> { 
     public Builder(JClass jClass) { 
     } 

     @Override 
     public JClass build() { 
      return new JClass(this); 
     } 
    } 
} 

Предупреждение находится в возвращаемом значении JClass.newBuilder:

Тип безопасности: Возвращение типа JClass.Builder для newBuilder () от типа JClass нуждается в непроверенной преобразование, чтобы они соответствовали B от типа JElement

ответ

2

Проблема заключается в том, что параметр B типа для метода newBuilder() не связан ни к чему:

abstract protected <B extends AbstractBuilder<J, B>> B newBuilder(); 

Этот метод подписи позволяет пользователю указать любой класс B extends AbstractBuilder<J, B> в качестве возвращаемого типа, а не только:

public static class Builder extends JElement.AbstractBuilder<JClass, Builder> { 

класс, который вы определили. Есть два эффективных решения проблемы:

1) Bind B к J в определении класса J «s, изменяя декларацию:

abstract public class JElement<J extends JElement<J>, B extends JElement.AbstractBuilder<J, B>> { 

2) Мое предпочтительное решение, изменить абстрактный метод подписи до:

abstract protected AbstractBuilder<J, ?> newBuilder(); 
+0

Thenk you. Ваше предпочтительное решение (2) работает очень хорошо для меня. – Arne

Смежные вопросы