Я думаю, что Контейнер выше - «правильный» выбор. Это также может быть обобщено для безопасности типов. Быстрый выбор в такой ситуации - это окончательный вариант массива. Хитрость заключается в том, что любые локальные переменные, на которые ссылается Runnable, должны быть окончательными и поэтому не могут быть изменены. Таким образом, вместо этого вы используете один элемент массива, где массив является окончательным, но элемент массива может быть изменен:
final Object[] result = new Object[1];
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result[0] = "foo";
}
}
System.out.println(result[0]);
Опять же, это «быстрое» решение для тех случаев, когда у вас есть анонимный класс, и вы хотите дать ему место для закрепления результата без определения определенного класса-контейнера.
UPDATE
Подумав немного об этом, я понял, что это прекрасно работает для использования типа слушателя и посетителя, когда обратный вызов находится в одном потоке. В этом случае, однако, Runnable выполняется в другом потоке, поэтому вы не гарантированно увидите результат после возврата syncExec. Правильное решение - использовать AtomicReference:
final AtomicReference<Object> result = new AtomicReference<Object>();
Display display = Display.getDefault();
display.syncExec(new Runnable()
{
public void run()
{
result.set("foo");
}
}
System.out.println(result.get());
Изменения в значении AtomicReference гарантированно будут видны всем потокам, как если бы оно было объявлено как volatile. Это подробно описано здесь .