从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;
}
编辑:当然,当我们使用像<T>
这样的泛型类型令牌时,它必须出现在类声明中。这里的类声明中没有<T>
和<?>
,但它仍然可以编译并正常运行。
答案 0 :(得分:6)
无法编译,因为您的类不是通用的(也没有任何方法)。在这个特定的例子中,joker(?)意味着ScheduledFuture可以被任何东西参数化。
有时候,如果你在里面使用另一个泛型类并且你不知道将要使用的确切类型,那么将整个类设为通用是没有意义的。 在此示例中,您有三个选项:
< ? >
) - 它允许通过FutureResult(String,Integer,您的自定义类)检索任何内容。您还可以将可能的泛型类型的范围缩小到某些子类,例如ScheduledGeneric< ? extends MyObject >
或超类:ScheduledGeneric< ? super MyObject >
答案 1 :(得分:2)
这是在类型参数中使用通配符的示例。即一般类型。
通配符参数化类型是泛型类型的实例,其中至少一个类型参数是通配符。通配符参数化类型的示例包括Collection<?>
,List<? extends Number>
,Comparator<? super String>
和Pair<String,?>
。
通配符参数化类型表示包含泛型类型的具体实例的类型族。正在使用的通配符类型决定了哪些具体参数化类型属于该族。
答案 2 :(得分:1)
那是Generic Type
...通常我们将String,Object或任何其他对象设置为泛型类型......但是在这里它们使它变得通用。和泛型类型代表它可以store or hold
的值。它通常用于Collections
..
两者之间没有多少差异...... - 采取所有类型的对象
<T>-is also called `formal type parameter` makes use of what ever type of object you pass in .. for instance you can do this with <T> and not with <?>
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
了解更多信息,请参阅http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf和http://download.oracle.com/javase/tutorial/java/generics/gentypes.html
答案 3 :(得分:1)
答案 4 :(得分:1)
假设this.executorService
是ScheduledExecutorService
的子类型(自Java 1.5起可用),scheduleWithFixedDelay()
的返回类型为ScheduledFuture<?>
。您无法将返回类型从ScheduledFuture<?>
更改为ScheduledFuture<T>
,ScheduledFuture<Integer>
或其他任何内容。但是,您可以将其更改为ScheduledFuture
,因为<?>
是一个通配符泛型类型参数,它近似于原始类型以实现向后兼容。
有关原始类型和泛型的详细讨论,请参阅What is a raw type and why shouldn't we use it?。
答案 5 :(得分:0)
它可以使用任何参数,如Object,String,Integer ....等等
现在,当您计划使用泛型时,您必须在天使括号内提供类型。
编辑:
<?>
严格适用于收藏集。
<T>
用作普通班级的类型或模板
答案 6 :(得分:0)
小丑?
可以持有任何类型。如果要对所有方法/成员使用相同的类型,则可以使整个类具有通用性。通过编写StopAlarmTask<T>
,您可以在整个班级中定义类型T
。
private final class StopAlarmTask<T> implements Runnable
{
StopAlarmTask(ScheduledFuture<T> aSchedFuture)
{
fSchedFuture = aSchedFuture;
}
public void run()
{ /* */ }
private ScheduledFuture<T> fSchedFuture;
}
答案 7 :(得分:0)
StopAlarmTask
不是通用类型。
在以下示例中,您不认为Foo
是泛型类型。
class Foo
{
Foo(int i)
{ }
doStuff(List<Integer> numbers)
{ }
}
StopAlarmTask
的构造函数使用泛型参数的事实不会使类泛型超过doStuff()
使{{1通用。
使用Foo
以通用方式“引用”泛型的声明,即没有特异性。在<?>
中它恰好是构造函数参数。它是泛型类型的“使用”,而不是泛型类型的声明,因为它“仅仅”是一个参数声明。
换句话说,简短的回答是方法中的参数
StopAlarmTask
适用于所有T的 StopAlarmTask(ScheduledFuture<?> aSchedFuture)
{ ... }
实例的所有对象。
以下是关于泛型的进一步背景。
使用ScheduledFuture<T>
或<T>
或其他任何内容来声明通用类型<E>
。具体来说,ScheduledFuture<T>
会在<?>
的声明中使用而不是,因为约定是使用单个大写字母。
请注意,以下测试代码,如果提供给编译器,将显示第一个类编译但第二个不编译,所以说有一个使用字母的约定实际上是轻描淡写。
ScheduledFuture<>
以下测试代码中说明,没有单字母约束,因此以下内容也是正确的。
class TGeneric1<E> {
List<E> list = new ArrayList<E>();
TGeneric1(E value) {
this.list.add(value);
}
E getHead() {
return this.list.get(0);
}
}
class TGeneric2<?> {
List<?> list = new ArrayList<?>();
TGeneric2(? value) {
this.list.add(value);
}
? getHead() {
return this.list.get(0);
}
}