Предупреждение о компиляции: непроверенный вызов на XXX в качестве члена необработанного типа

Я получаю предупреждение компилятора:

предупреждение: [unchecked] unchecked вызов setView (V) в качестве члена необработанного типа AbstractPresenter

   this.presenter.setView(this);

где V - переменная типа:

V расширяет AbstractView, объявленный в классе AbstractPresenter

Код класса AbstractPresenter следующий:

public abstract class AbstractPresenter<V extends AbstractView, M> 
implements Presenter<V, M> {

    private M model;
    private V view;

    @Override
    public final V getView() {
        return this.view;
    }

    public final void setView(V view) {
        if (view == null) {
            throw new NullPointerException("view cannot be null.");
        }

        if (this.view != null) {
            throw new IllegalStateException("View has already been set.");
        }
        this.view = view;
    }

    @Override
    public final M getModel() {
        return this.model;
    }

    protected final void setModel(M model) {
        if (model == null) {
            throw new NullPointerException("model cannot be null.");
        }        
        this.model = model;
    }
}

Метод setView вызывается в классе AbstractView ниже:

public abstract class AbstractView<P extends AbstractPresenter> extends 
UserControl {
    private final P presenter;

    public AbstractView(P presenter) {
        this.presenter = presenter;
        this.initialisePresenter();
    }

    private void initialisePresenter() {
        if (this.presenter == null){
            throw new IllegalStateException();
        }

        this.presenter.setView(this); //This is the call that raises the warning
    }

    protected P getPresenter() {
        return this.presenter;
    }
}

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

Я не понимаю, почему предупреждение возникает, поскольку тип V принудительно объявляется классом AbstractPresenter:

public abstract class AbstractPresenter<V extends AbstractView, M> 
implements Presenter<V, M> 

Это просто предупреждение, и я мог бы игнорировать его, но я хотел бы понять, почему это происходит, и я хочу, чтобы мой код был как можно более чистым.

Ответы

Ответ 1

Ваши типы являются сырыми - то есть ваши общие типы привязаны к типу, который сам имеет тип, но вы его не предоставили, поэтому он необработанный.

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

public abstract class AbstractPresenter<V extends AbstractView<V>, M> implements Presenter<V, M>

и

public abstract class AbstractView<P extends AbstractPresenter<P> extends UserControl

Ответ 2

Ваша проблема в этой строке:

public abstract class AbstractView<P extends AbstractPresenter> extends

Ваш P объявлен как тип, который расширяет raw AbstractPresenter. В принципе, мы не знаем, что такое V и M этого типа.

Поэтому this.presenter относится к этому необработанному типу, и мы не знаем его V и M. Таким образом, когда вы вызываете его setView с помощью this, компилятор не может определить, являются ли типы правильными или нет.

То же самое верно для

public abstract class AbstractPresenter<V extends AbstractView, M> 

V - это тип, который расширяет raw AbstractView, и мы не знаем, каков его базовый тип. Таким образом, компилятор не может выполнять работу, для которой предназначены дженерики.

Всякий раз, когда вы делаете такие объявления типа, не забудьте указать типы всех общих типов в объявлении и использовать переменные типа, которые правильно представляют отношения между ними.

Ответ 3

Я хотел добавить комментарий, но не мог, поскольку у меня недостаточно репутации.

ваши типы являются сырыми. ведущий в AbstractView является сырым типом, поскольку общие параметры, переданные в Abstract View, являются raw