这是具体的参数化类型吗?

Fan*_*rns 3 java

如果我理解正确的话,以下是通用类型:

class Example<T> {}
Run Code Online (Sandbox Code Playgroud)

以下是具体参数化类型:

Example<String>
Run Code Online (Sandbox Code Playgroud)

以下不是具体参数化类型:

Example<? extends Number>
Run Code Online (Sandbox Code Playgroud)

鉴于以下内容,有人可以向我解释 Example 是否是具体参数化类型?

Example< OtherExample<? extends Number> >
Run Code Online (Sandbox Code Playgroud)

如果它不是具体的,那么是否可以说如果类型参数本身是通配符,或者任何嵌套类型参数是通配符,那么最外层的类型因此不是具体的?

更新

我现在意识到术语“具体参数化类型”可能不是官方的 Java 术语。

我从以下来源获取它:http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#Topic2

结论

我被说服了:

Example< OtherExample<? extends Number> >
Run Code Online (Sandbox Code Playgroud)

是具体参数化类型(就 GenericsFAQ 的术语而言),因为它不直接包含通配符(“?”),并且可以与“new”关键字一起使用。

谢谢!

Rad*_*def 5

在这里的其他地方安吉莉卡常见问题解答是这样说的:

通配符参数化类型不是可以出现在新表达式中的具体类型。

但为了扩展这一点,我想说有几种不同类型可以作为类型参数提供。

给定示例类:

class Example<T> {
    T value;
}
Run Code Online (Sandbox Code Playgroud)

原始类型(无类型参数):

new Example();
Run Code Online (Sandbox Code Playgroud)

原始类型有点像“擦除”类型。由于T没有界限,原始的Example<T>行为很像Example<Object>. 不同之处在于原始类型导致泛型类型系统在很大程度上被忽略。在实践中,不要使用它。这是为了向后兼容。

通用类型参数(类型来自其他地方):

class HasExample<T> {
    Example<T> myExample = new Example<T>();

    HasExample(T value) {
        myExample.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

then的类型Example接收提供给 的任何类型HasExample

“具体”类型参数:

new Example<String>();
Run Code Online (Sandbox Code Playgroud)

这意味着示例的类型实际上是已知的。

除了原始类型和泛型之外,这些是泛型类实例化的三种方式。

通配符类型参数(未知):

static void handle(Example<?> example) {
    System.out.println(example.value);
}
Run Code Online (Sandbox Code Playgroud)

通配符表示Example曾经一个具体类型,但我们不确定它是什么。由于我们不知道它是什么,通配符不允许以某些方式使用参数化成员。在上面的方法中,我们仍然可以打印它(toString间接调用),因为我们可以确定它是一个Object.

关于复杂的声明是否应该被视为具体的,它既是肯定的,也是否定的,但我想说的是,大部分是肯定的。假设我们有以下附加类:

class Holder<T> {
    T held;
}
Run Code Online (Sandbox Code Playgroud)

然后可以执行以下操作:

Holder<Example<? extends Number>> holder =
    new Holder<Example<? extends Number>>();
Run Code Online (Sandbox Code Playgroud)

的 type 参数holder是一个具体类型: Example,在这个意义上:

  • 尽管包含通配符,但它本身不是类型变量或通配符。
  • 我们可以用这种类型实例化一个新的实例Holder

Holder单独考虑和的类型可能很有用Example,因为它们各自的类型参数对我们可以对实例执行的操作有不同的影响Holder

我们可以执行以下操作:

Example<Integer> example = new Example<Integer>();
example.value = Integer.valueOf(0);
// set holder.held
holder.held = example;
// get holder.held, but we lose some type information
Example<? extends Number> example = holder.held;
// access and use a member of the Example
Number number = example.value;
System.out.println(number.intValue());
Run Code Online (Sandbox Code Playgroud)

但是,我们不能这样做:

// set parameterized member of the Example
holder.held.value = Integer.valueOf(1);
Run Code Online (Sandbox Code Playgroud)

这是通配符的效果,这就是为什么我们可以说声明的类型holder“不完全具体”。但请注意,这是对嵌套对象的影响。通配符并不直接限制我们使用Holder实例的方式。它仅限制我们使用实例成员的方式Example

出于这些原因,我想说,将A<B<? extends C>>(带有嵌套通配符)之类的类型视为具体类型是合理的,但有一些注意事项。