Java中<?>标记的含义是什么?

H2O*_*aCl 7 java generics

<?>从www.JavaPractices.com复制的此代码中令牌的含义是什么?当我用更常规的<T>用于泛型类型的替换它时,它无法编译.(错误:T无法解析为某种类型.)为什么?

// <?> occurs 3 times in the entire program.  When it is replaced with <T> the
// program no longer compiles.

void activateAlarmThenStop()
{
    Runnable myPeriodicTask = new PeriodicTask();
    ScheduledFuture<?> soundAlarmFuture = 
        this.executorService.scheduleWithFixedDelay(myPeriodicTask, 
                                          startT, 
                                          period, 
                                          TimeUnit.SECONDS
                                         );
    Runnable stopAlarm = new StopAlarmTask(soundAlarmFuture);
    this.executorService.schedule(stopAlarm, stopT, TimeUnit.SECONDS);
}

private final class StopAlarmTask implements Runnable 
{
    StopAlarmTask(ScheduledFuture<?> aSchedFuture)
    {
        fSchedFuture = aSchedFuture;
    }

    public void run() 
    {
        CConsole.pw.println("Stopping alarm.");
        fSchedFuture.cancel(doNotInterruptIfRunningFlag);

        executorService.shutdown();
    }
    private ScheduledFuture<?> fSchedFuture;
}
Run Code Online (Sandbox Code Playgroud)

编辑:当然,当我们使用泛型类型的标记时<T>,它必须出现在类声明中.这里没有<T>也没有<?>在类声明中,但它仍然编译并正常运行.

omn*_*nom 6

它无法编译,因为您的类不是通用的(也没有任何方法).在这个特定的例子中,joker(?)意味着ScheduledFuture可以被任何东西参数化.

有时,如果您在内部使用另一个泛型类并且您不知道将使用的确切类型,那么将整个类设为通用是没有意义的.在此示例中,您有三个选项:

  1. 使StopAlarmTask通用(在这种情况下没有意义)
  2. 在ScheduledFuture中使用具体类型,但它只是一种可能的结果类型,例如String或Integer
  3. 使用wildcard(< ? >) - 它允许通过FutureResult(String,Integer,您的自定义类)检索任何内容.您还可以将可能的泛型类型的范围缩小到某些子类,例如ScheduledGeneric< ? extends MyObject >或超类:ScheduledGeneric< ? super MyObject >