Каков разумный способ изменить примитивную переменную из анонимного Java-класса? - PullRequest
4 голосов
/ 04 мая 2010

Я хотел бы написать следующий код:

boolean found = false;
search(new SearchCallback() {
  @Override void onFound(Object o) { found = true; }
});

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

final class MutableReference<T> {
  private T value;
  MutableReference(T value) { this.value = value; }
  T get() { return value; }
  void set(T value) { this.value = value; }
}

но в итоге при правильном форматировании это занимает много места, и я бы не стал изобретать велосипед, если это вообще возможно Я мог бы использовать List<Boolean> с одним элементом (либо изменить его, либо очистить список), либо даже Boolean[1]. Но все кажется странным, так как ни один из вариантов не используется так, как предполагалось.

Какой разумный способ сделать это?

Ответы [ 4 ]

4 голосов
/ 04 мая 2010

Я склонен использовать булевский метод [1], который вы упомянули:

final boolean[] found = {false};
search(new SearchCallback() {
  @Override void onFound(Object o) { found[0] = true; }
});

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

3 голосов
/ 04 мая 2010

Вы можете перейти на все функции:

Boolean found = search(new SearchCallback<Boolean>() {
    @Override Boolean onFound(Object o) { return true; }
});

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

2 голосов
/ 04 мая 2010

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

Другой вариант в этой ситуации - сделать закрытый класс следующим образом:

   private class Searcher implements SearchCallback {
        private boolean found;
        @Override public void onFound(Object o) { found = true; }
        public boolean search() {
              OuterClass.this.search(this);
              return found;
        }
   }

А затем используйте его так:

  boolean found = new Searcher().search();

Редактировать: Если я правильно понимаю комментарий Тома, он предлагает это в качестве альтернативы

 public void foo() { //This is the method that enclosed the code in your question
     new SearchCallBack() {
         private boolean found;
         @Override public void onFound(Object o) { found = true; }
         {
            //The code that was before this in your method
            search(this);
            //The code that was after this in your method
         }
     };
 }

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

0 голосов
/ 04 мая 2010

Если вы действительно не можете использовать поле, ответы Майкла кажутся правильными.

В любом случае. Я не знаю, к каким сигнатурам вы можете прикоснуться, но мне кажется, что этот обратный вызов намеревается что-то сделать (когда поиск будет успешным) с / к найденному объекту. Вместо этого вы намереваетесь уведомить вызывающего абонента о методе поиска, что он что-то нашел. Было бы намного более естественным, если бы ваш seach () метод был создан для возврата логического значения (метод обязательно вызовет s.onFound () где-нибудь, если поиск будет успешным, затем установите внутренний found отметьте там и верните его).

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