неконечная переменная внутреннего класса java

Мне нужно было изменить переменные внутри внутреннего класса, и я получил печально известную ошибку «Не могу ссылаться на неконечную переменную внутри внутреннего класса, определенного в другом методе».

void onStart(){
  bt.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
       int q = i;
     }
  });
}

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

class temp{
  int q;
}

void onStart(){
  final temp x = new temp();
  bt.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
       x.q = i;
     }
  });
}

Кажется, это то, что мне нужно, и это работает, но мне интересно, как правильно решить проблему. Кроме того, я действительно ненавижу использовать слово temp в названии своего класса. Есть ли реальный термин программирования для того, что я сделал, чтобы я сделал более описательное имя для своего класса?


person Aaron Greenberg    schedule 03.07.2012    source источник


Ответы (4)


Вы можете просто создать внутренний класс вместо анонимного (как вы сейчас делаете). Затем у вас есть конструктор и любые другие методы, которые вы хотите установить для своих членов. Не требуется хакерства (например, массив из 1 случая).

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

Например:

private MyListener listener = new MyListener();

void onStart(){
  bt.setOnClickListener(listener);
}

class MyListener implements OnClickListener
{ 
    String name;
    int value;

    void setName(String newName)
    {
        name = newName;
    }

    void setValue(int newValue)
    {
        value = newValue;
    }

    public void onClick(View v) 
    {
        // Use the data for some unknown purpose
    }
}

Если задействовано несколько потоков, также необходимо использовать соответствующую синхронизацию.

person Robin    schedule 03.07.2012
comment
Браво. Другая приятная вещь заключается в том, что этот внутренний класс является более расширяемым и пригодным для повторного использования. ИМО, анонимные внутренние классы почти всегда плохая идея. - person user949300; 03.07.2012
comment
Они хорошо работают как одноразовые классы стилей действий, обработчики определенных событий, в которых действия могут выполняться на основе входных данных. Очень распространен в программировании с графическим интерфейсом, что является его примером. За исключением того, что в этом случае взаимодействие между классами усложняет ситуацию. - person Robin; 04.07.2012
comment
Это то, что я искал! Спасибо! - person Aaron Greenberg; 05.07.2012

Я разместил аналогичный ответ в моем другая тема здесь. По сути, идея состоит в том, чтобы создать «оболочку», которая охватывает почти любой тип Object. Поскольку final в Java означает "без переназначения", а не "константа", этот трюк работает отлично. Но, как упоминалось в исходном посте, будьте осторожны при использовании его в многопоточной среде.

person Sanjay T. Sharma    schedule 03.07.2012

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

Проще говоря, если внутреннему классу необходимо его изменить, сделайте его переменной во внутреннем классе.

person Rob Trickey    schedule 03.07.2012

Поскольку вы, кажется, устанавливаете несколько вещей (из комментариев), создайте метод в основном классе, button1WasClicked() (лучшее имя может быть doUpdate, doSave и т. д. - что-то, относящееся к тому, что делает кнопка), поместите туда правильный код , и вызвать его из внутреннего класса/слушателя. (Если вы используете Swing, я бы сделал это действием, YMMV)

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

person user949300    schedule 03.07.2012