变量可能尚未针对最终变量和匿名类进行初始化

时间:2012-03-31 14:23:48

标签: java variables initialization

我写了这段代码:

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 个答案:

答案 0 :(得分:1)

编译器是正确的。这里确实存在问题。

问题出现是因为Java处理匿名SchedulerHandle类中Runnable变量的使用方式。实例化Runnable类时,使用合成构造函数参数将SchedulerHandle的值传递给匿名类。这个值存储在一个隐藏属性中,这就是run()方法使用的...而不是包含该类的范围中的变量。

那为什么会导致错误?

嗯,我上面描述的机制意味着在SchedulerHandle实例创建之前需要初始化Runnable。但实际上,在scheduleWithFixedDelay调用返回后,它会在稍后初始化。因此,当需要变量的值时,它尚未初始化。

答案 1 :(得分:0)

因为SchedulerHandle是最终的并且您没有立即定义它,所以编译器会警告您,它可能没有在run()方法中初始化。 只需:

  

final ScheduledFuture SchedulerHandle = ExtractorTimer.scheduleWithFixedDelay(...   

更新:这完全错了。让我们看看,你想每60秒调用一次DB.buildConnection(),直到它返回true。遗憾的是,您无法引用从调用方法的Runnable中的scheduleWithFixedDelay()返回的SchedulerHandle,因为必须首先定义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()s也将不会执行。使其可用的唯一方法是创建一个新的ScheduledExecutorService - 这是这种方法的缺点。

因此,如果你只使用ExtractorTimer来完成这一项任务,一切都应该没问题。

答案 2 :(得分:-2)

尝试:

final ScheduledFuture<?> SchedulerHandle = null;