如果我理解正确,以下是通用类型:
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”关键字一起使用。
谢谢!
答案 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
的新实例。分别考虑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());
但是,我们不能这样做:
// 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<?>>
。