2017-01-29 2 views
1

У меня есть этот код:Lambda limitions в использовании с runnables

Task.doTask(new Runnable(){ 
    int bound = 0; 
    @Override 
    public void run(){ 
     switch (bound){ 
      case 0: 
       break; 
      case 1: 
       finishTask(); 
       break; 
     } 
     bound++; 
    } 
    }); 

Я могу поставить инициировать int границы и использовать его в качестве индикатора выполнения легко с этим

Task.doTask(() ->{ 
     int bound = 0; 
     switch (bound){ 
      case 0: 
       break; 
      case 1: 
       finishTask(); 
       break; 
     } 
     bound++; 
    }); 

, но с помощью лямбды я могу 't инициировать связанный, поэтому он всегда 0;

+0

Это потому, что тело лямбда определяет метод 'run' внутри экземпляра' Runnable', который передается методу 'doTask'. – blazs

ответ

2

2 части коды вы Включенная РАЗНЫХ (не из-за lambda expressions)

Task.doTask(new Runnable(){ 
int bound = 0; // initialize the bound variable as 'global' 
@Override 
public void run(){ 
    switch (bound){ 
     case 0: 
      break; 
      case 1: 
       finishTask(); 
       break; 
    } 
    bound++; // the `bound` variable is `shared` across run calls 
} 
}); 

Task.doTask(() ->{ 
    int bound = 0; // initialize the bound variable EVERY TIME you call it 
    switch (bound){ 
     case 0: 
      break; 
      case 1: 
       finishTask(); 
       break; 
    } 
    bound++; // this is useless - bound is always initialize to zero for EVERY CALL 
}); 
+0

Проблема, с которой я сталкиваюсь, заключается в том, что привязка инициализируется каждый раз с использованием лямбда, я хочу использовать лямбда, но инициализирую ее только один раз, так как в первом примере – user7148508

+0

вы можете использовать переменную 'bound' в классе scope - позволяя ей сохранять его состояние всякий раз, когда вы делаете изменения в своем лямбда-выражении – ymz

+0

Я думаю, это один из способов сделать это, но будет становиться растущим препятствием, так как класс растет – user7148508

2

Это потому, что тело лямбды определяет метод run внутри экземпляр Runnable, который получает передается Метод doTask.

Я бы не назвал это ограничение --- lambdas - это просто синтаксическая стенограмма для передачи экземпляра классов одного метода.

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

1

Вы можете увеличивать изменяемую обертку за пределы вашего лямбда, например:

AtomicInteger bound = new AtomicInteger(0); 
Task.doTask(() -> { 
    switch (bound.get()){ 
     case 0: 
      break; 
      case 1: 
       finishTask(); 
       break; 
    } 
    bound.incrementAndGet(); 
}); 
+0

Имеет ли это какое-либо преимущество по сравнению с 'int', определенным за пределами лямбда *? –

+0

Я бы предпочел не создавать переменную класса – user7148508

+1

@Shashwat Внешние переменные, на которые ссылаются внутри лямбда, должны быть окончательными или фактически окончательными, то есть вы не сможете изменить 'int', определенный вне лямбда. – shmosel

0

Вы можете прочитать окончательные переменные лямбды, но ваш Runnable не имеет ни одно государства больше, как ЯМЗ уже указывался. Lambdas можно использовать для легкой записи функций, но то, что вы изначально использовали, является сдержанным.

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