Локальная переменная должна быть объявлена ​​как final

Я получаю сообщение об ошибке "доступ к локальной переменной осуществляется из внутреннего класса; необходимо объявить его окончательным". Кажется, это нормально, но я не думаю, что это лучшее решение, поэтому я надеялся, что кто-то еще может мне помочь. Вот мой код:

public void showPublisherBox(JComboBox box) {
    if (publisherBox == null) {
        publisherBox = new AddPublisherForm();
        publisherBox.setLocationRelativeTo(this);
    }
    publisherBox.addWindowListener(new WindowAdapter()
    {
    public void windowClosing(WindowEvent we)
    {
        this.populatePublishers(box);
    }

        private void populatePublishers(JComboBox box){
            box.setModel(db.getPublishers());
        }
    });
    publisherBox.setVisible(true);
}

Форма издателя - это просто новый JFrame, который открывается и принимает некоторую информацию, и когда он закрывается, я хочу, чтобы JComboBox был повторно заполнен путем установки модели из моего метода db.getPublishers().

Итак, есть ли лучший способ сделать то, что я здесь делаю, или мне придется объявить что-то окончательным?

Спасибо


person Samsquanch    schedule 01.05.2011    source источник


Ответы (5)


Поскольку вы не изменяете box во внешнем коде, использование final является правильным способом решения этой проблемы. Это обещание себе (и компилятору), что значение box не изменится во внешней области видимости. Компилятор сообщит вам, если вы нарушите это обещание.

Использование final не требует времени компиляции или времени выполнения.

person Greg Hewgill    schedule 01.05.2011

Когда анонимный внутренний класс (такой как ваш WindowAdapter) ссылается на переменные в охватывающих областях (например, «коробка»), Java требует, чтобы они были объявлены final.

Одним из способов избежать объявления box как final было бы сделать ваш WindowAdapter именованным классом, который принимает box в качестве параметра конструктора:

public void showPublisherBox(JComboBox box) {
    if (publisherBox == null) {
        publisherBox = new AddPublisherForm();
        publisherBox.setLocationRelativeTo(this);
    }

    publisherBox.addWindowListener(new MyWindowClosingHandler(box, db));
    publisherBox.setVisible(true);
}

// ...

class MyWindowClosingHandler extends WindowAdapter {
    private JComboBox box;

    MyWindowClosingHandler(JComboBox box, DB db) {
        this.box = box;
        this.db = db;
    }

    public void windowClosing(WindowEvent we) {
        populatePublishers();
    }

    private void populatePublishers(){
        box.setModel(db.getPublishers());
    }
});

}

person pholser    schedule 01.05.2011

Неа. В этом случае объявить как final. Ссылка все равно не меняется.

person Chris Dennett    schedule 01.05.2011

Локальные переменные, используемые локальными классами, должны быть объявлены как final. В этом случае переменная является параметром метода, которому вы все равно не назначаете, поэтому я не вижу причин, почему бы не объявить ее как final.

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

person Eyal Schneider    schedule 01.05.2011

Вы должны вводить «Final» каждый раз, когда объявляете переменную — я понятия не имею, почему Java не сделала final значением по умолчанию и вместо этого потребовала ключевое слово «Variable» или что-то в этом роде. Я просто говорю, что большинство переменных должны быть окончательными, если не доказано обратное.

Тем не менее, вы всегда можете создать полный класс вместо анонимного внутреннего класса и передать переменную в конструктор - это будет "правильный" способ сделать это. Анонимные внутренние классы в любом случае являются плохой привычкой — они препятствуют повторному использованию кода (внутренний класс нельзя повторно использовать в качестве слушателя в другом месте, тогда как, если бы это был полный класс, его было бы легко использовать повторно — я использовал эту технику при рефакторинге). для устранения огромных груд избыточного кода.

person Bill K    schedule 01.05.2011
comment
+1 Я согласен с вашим первым абзацем, когда речь идет о локальных переменных или аргументах метода. - person Paul Bellora; 29.08.2011