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

时间:2014-01-19 18:11:20

标签: java

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

class Example<T> {}

以下是具体参数化类型:

Example<String>

以下是具体参数化类型:

Example<? extends Number>

鉴于以下情况,有人可以向我解释一下,例子是否为具体的参数化类型?

Example< OtherExample<? extends Number> >

如果它不是具体的,那么如果一个类型参数本身是一个通配符,或者任何嵌套的类型参数是一个通配符,那么最外面的类型是不是具体的呢? / p>

更新

我现在意识到术语混凝土参数化类型可能不是官方的Java术语。

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

结论

我被说服了:

Example< OtherExample<? extends Number> >

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

谢谢!

5 个答案:

答案 0 :(得分:4)

Elsewhere in here FAQ Angelika说:

  

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

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

给出示例类:

class Example<T> {
    T value;
}

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

new Example();

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

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

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

    HasExample(T value) {
        myExample.value = value;
    }
}

然后Example的类型会收到提供给HasExample的任何类型。

'具体'类型参数:

new Example<String>();

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

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

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

static void handle(Example<?> example) {
    System.out.println(example.value);
}

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

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

class Holder<T> {
    T held;
}

然后可以执行以下操作:

Holder<Example<? extends Number>> holder =
    new Holder<Example<? extends Number>>();

holder的类型参数是具体类型:Example,意思是:

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

分别考虑HolderExample的类型可能很有用,因为它们各自的类型参数对我们可以对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());

但是,我们不能这样做:

// set parameterized member of the Example
holder.held.value = Integer.valueOf(1);

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

由于这些原因,我认为将A<B<? extends C>>(带有嵌套通配符)等类型视为具体内容是合理的,但需要注意几点。

答案 1 :(得分:0)

据我所知,具体是课堂不抽象。 '参数化'或 通用 (我首选的方式)是你正确猜到的例子和无界的通配符?与它具体有关示例与示例相同。

那就是说,你可以将abstract class Example<T>称为非具体的通用类型,但我从未见过有人这样称呼它。

因此,考虑到你提到的来源的术语,他们声称具体意味着缺乏通配符(无界,?,是他们唯一提到的 - 所以不确定有界类型是否也不是'具体)。我只能向您推荐有关该问题的其他信息来源:http://docs.oracle.com/javase/tutorial/java/generics/

答案 2 :(得分:0)

你与

有所不同
class MyClass<T>{}

你不知道T的参数是什么:

class MyOtherClass extends MyClass<String>

现在你知道MyOtherClass的类型是哪个 是一个MyClass。

有通配符有趣的东西

class MyClass<? extends Number>{}
class MyOtherClass extends MyClass<Integer>

但想法是一样的;

然而

  MyUnfinishedClass<T> extends MyClass<T>

不具体,因为T尚未知晓。

你的source - 这是一个关于泛型的最佳网页之一 - 说的是同样的。 MyClass不是具体的参数化类,MyOtherCLass是具体的参数化类。 JVM将为每个不同的参数化类创建一个新类,它将导致class MyIntegerClass extends MyClass<Integer>class MyDoubleClass extends MyClass<Double>甚至class MyNumberClass extends MyClass<Number>之间的区别。

这被称为逆变,可能是您的下一个问题。

答案 3 :(得分:0)

唯一的区别是?。不带?的类型是具体参数化类型

唯一的区别是通配符(界定为T,无界界如?)。没有通配符的类型是具体参数化类型

答案 4 :(得分:0)

Example< OtherExample<? extends Number> >具体:也就是说,您可以实例化此类的实例。就像您可以实例化ArrayList<Collection<?>>