Возможно, переменная не инициализирована для конечной переменной и анонимного класса - PullRequest
2 голосов
/ 31 марта 2012

Я написал этот код:

ScheduledExecutorService ExtractorTimer=Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> SchedulerHandle;
SchedulerHandle =ExtractorTimer.scheduleWithFixedDelay(
    new Runnable() {
        public void run() {
            if(DB.buildConnection()){
                  SchedulerHandle.cancel(false);
            }
        }
     },0, 60,java.util.concurrent.TimeUnit.SECONDS);

Это дает это:

Variable SchedulerHandle might not have benn initialized

В чем проблема?
Как я могу это исправить?

Ответы [ 3 ]

1 голос
/ 31 марта 2012

Компилятор правильный.Здесь на самом деле проблема.

Проблема возникает из-за способа, которым Java обрабатывает использование переменной SchedulerHandle в анонимном классе Runnable.Когда создается экземпляр класса Runnable, синтетический параметр конструктора используется для передачи значения SchedulerHandle анонимному классу.Это значение хранится в скрытом атрибуте, и это то, что метод run() использует ... а не переменную в области действия, охватывающей класс.

Так почему это вызывает ошибку?

Хорошо, механизм, который я описал выше, означает, что SchedulerHandle необходимо инициализировать перед созданием экземпляра Runnable.Но на самом деле он инициализируется позже, после возврата вызова scheduleWithFixedDelay.Таким образом, в момент, когда требуется значение переменной, она не была инициализирована.

0 голосов
/ 31 марта 2012

Попробуйте:

final ScheduledFuture<?> SchedulerHandle = null;
0 голосов
/ 31 марта 2012

Поскольку SchedulerHandle является окончательным, и вы не определили его сразу, ваш компилятор предупреждает вас, что он может не инициализироваться в методе run (). Просто сделайте:

final ScheduledFuture SchedulerHandle = ExtractorTimer.scheduleWithFixedDelay (...

Обновление: это было просто неправильно. Давайте посмотрим, вы хотите вызывать DB.buildConnection () каждые 60 секунд, пока он не вернет true. К сожалению, вы не можете ссылаться на SchedulerHandle, возвращенный от scheduleWithFixedDelay () в Runnable, с которым вы вызываете метод, потому что Runnable должен быть определен в первую очередь - но он не знает, что такое SchedulerHandle, потому что он не существует в этой точке.

Таким образом, альтернативный способ отменить процесс - завершить работу службы ScheduledExecutorService, например:

ScheduledExecutorService ExtractorTimer=Executors.newScheduledThreadPool(1);
final ScheduledFuture<?> SchedulerHandle;
SchedulerHandle =ExtractorTimer.scheduleWithFixedDelay(
    new Runnable() {
        public void run() {
            if(DB.buildConnection()){
                  ExtractorTimer.shutdown();
            }
        }
    },0, 60,java.util.concurrent.TimeUnit.SECONDS);

Но учтите, что если вы сделаете это, вы не сможете повторно использовать ExtractorTimer, и любая данная задача будет отменена! Будущее schedule () также не будет выполнено. Единственный способ сделать его снова пригодным для использования - это создать новый ScheduledExecutorService - это недостаток этого подхода.

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

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