我一直在尝试泛型,很快我就遇到了一些我无法解释的事情
例如:
import java.util.*;
public class Main {
public static void main(String[] args) {
//We cannot create List<?> l = new ArrayList<?>();
List<?> l = MagicClass.factory();
}
static class MagicClass {
public static <T> List<T> factory() {
return new ArrayList<T>();
}
}
}
我不明白
<?>
没有定义。
我们无法创建列表l=new ArrayList();
如果你真的想做,你可以做
List<?> l = new ArrayList<Object>();
或者
List<?> l = new ArrayList<String>();
或者
List<?> l = new ArrayList<Math>();
或者
List<?> l = new ArrayList<SomeBogusIrrelevantClass>();
所有这些都是正确的。只要选择满足边界的任何类型;它甚至不需要与你正在做的事情相关。
从这里,你可以看出为什么你试图做的事情是荒谬的——你有一个列表可以是ArrayList
您不能向其添加任何内容(除了
null
)。所以你有一个列表,其中元素只能有值null
;唯一可以改变的是有多少个null
s。但在这种情况下,您最好使用一个整数。
示例:以下代码无法编译:
ArrayList<?> foo = new ArrayList<String>();
foo.add("bar");
这是因为Java不知道
foo
中的t
是什么。foo
可能是ArrayList
例如,如果你想制作一个可以接受各种
列表的方法,就可以使用它
永远不能用通配符构造实例
以下代码无法编译:
ArrayList<?> foo = new ArrayList<?>();
这是因为在施工时,Java必须知道你会选择哪种类型。
但在许多情况下,它被用作有界通配符。举个典型的例子:
public void drawAll(List<? extends Shape> shapes) {
//...
}
这个方法给出了一个
Shape
的列表
使用通配符实例化泛型类型会生成编译错误,因为通配符表示任何类型,而实例化的ArrayList
应该有一个具体的类型。通配符可以用于变量或参数类型,但不能用于创建泛型类型的实例。
本教程页面也提到了这一点:
在泛型代码中,问号(?
),称为通配符,表示未知类型。通配符可以在多种情况下使用:作为参数、字段或局部变量的类型;有时作为返回类型(尽管编程实践中最好更具体)。通配符永远不会用作泛型方法调用、泛型类实例创建或超类型的类型参数。
另一方面,在工厂
方法中,T
是编译器将推断的类型参数,并且由于List
问题内容: 我遇到了一个涉及静态泛型方法的奇怪情况。这是代码: 我为什么不必在表达式中指定任何类型参数?这是某种类型推断吗?如果我想对此进行明确说明,如何指定类型参数? 问题答案: 是的,根据JLS第15.12.2.8节,这是基于分配目标的类型推断。明确地说,您可以这样称呼:
我有Java8 Groovy 2.4.12和下面的代码编译和运行。 但是如果你注释掉< code>return,编译器会说 此外,如果您注释掉值分配,那么它又可以了。因此,下面的代码编译并运行: 这似乎是一种特殊情况,只有在以下情况下才会发生: 注释 具有两个参数的泛型方法;第一个是泛型类型,第二个是相同泛型类型的接口 调用该泛型方法,第二个参数作为闭包,全部包装在另一个闭包中。 调用前的变量声明
问题内容: 没有静态成员可以使用类型参数,但是可以使用泛型类型参数调用静态成员吗?例如:- 这里的add()是一个静态方法。 在类似的主题上也有一些C#问题和答案,但是我不太确定如何在Java中使用它。 问题答案: 不,如果A是泛型类型,则无法执行。(Bozho对fast的回答是:),可能认为A是具体类型。 可行的方法如下。 但这可能不是您想要的。 阅读您的评论后,听起来您真正想要做的是: 您
问题内容: 我想知道用这样的签名调用静态方法的正确方法是什么: 由于某种原因,我很想这样称呼它: 但是除非我将其更改为:否则它不会编译: 我只是想知道为什么它不需要右侧的提示。而是给了我编译错误。它说它期望在右侧的提示后加上分号。第二个方法是调用该方法的正确方法吗?有人可以给我一些启示吗? 问题答案: 如图所示这里,要调用的方法的方法是: 该方法所在的类的名称在哪里。
安吉丽卡·兰格(Angelica Langer)在关于仿制药的常见问题解答中说(参见Technicalities.FAQ822): 如果这些方法具有具有不同边界的类型参数,则它们不会重写,因为这些方法的签名不是重写等价的。请记住,类型参数边界是泛型方法签名的一部分。 示例(泛型子类型方法重载泛型超类型方法;不推荐): 我不明白为什么方法在类中重载。据我所知,这应该是一个编译时错误,因为在和中具有相
我有一个Foo和Bar对象的列表,以及每个相应对象的转换器。 Convert-method需要有所不同,因为Bar1与Bar2和Bar3等有很大不同,但是我想创建一个方法来处理所有可能的列表。 是否可以创建一个泛型方法,根据列表的内容调用相应的非泛型方法? 到目前为止,我已经尝试过了: 但这并不能编译,因为"无法解析方法'Converts(T, S)'" 有什么想法吗?