Java 为什么我们需要提供两次通用信息?

Java 为什么我们需要提供两次通用信息?,java,generics,language-design,Java,Generics,Language Design,另一个关于Java中泛型的非常基本的问题,直接来自于。我们不是通过编写下面的代码两次向编译器提供相同的信息吗。为什么我们需要在左手侧和右手侧同时提供这些功能 List<Number> numbers = new ArrayList<Number>(); List number=new ArrayList(); 编辑:正如我在一些答案中看到的那样,java 7以后不再需要它。但是我想知道在java 7之前不可能的原因是什么?因为java 7之前不支持构造函数的泛型类型推

另一个关于Java中泛型的非常基本的问题,直接来自于。我们不是通过编写下面的代码两次向编译器提供相同的信息吗。为什么我们需要在左手侧和右手侧同时提供这些功能

List<Number> numbers = new ArrayList<Number>();
List number=new ArrayList();

编辑:正如我在一些答案中看到的那样,java 7以后不再需要它。但是我想知道在java 7之前不可能的原因是什么?

因为java 7之前不支持构造函数的泛型类型推断。这在Java7中由菱形操作符解决。
您还可以编写通用工厂方法作为解决方案,如:

 public static <T> List<T> createArrayList() {
      return new ArrayList<T>();
 }
公共静态列表createArrayList(){
返回新的ArrayList();
}
然后

List List=createArrayList();
这是有问题的,但有效。对于映射和其他多参数泛型类型,可能会有很好的回报



编辑:也许语言设计者决定不支持泛型类型推断,因为他们实现了带有类型擦除的泛型。另一个值得怀疑的决定,我想。。。否则,不要认为在早期的java版本中有任何严重的理由反对这个特性。(根据Peter Lawrey的附录,它仍然不存在。)

引入了菱形操作符,可以删除这些冗余信息

请参见此SO链接


从我的阅读/理解来看,我不认为泛型在java中做得那么好。这个最后介绍的操作员是一个令人痛苦的工作。事实上,在我看来,这是擦掉的。它确实起到了作用,但我认为它可能会更好,因为一个是参考,一个是实现。该行的左侧设置了用于存储实例化变量的引用。由于Java使用“运行时类型擦除”来实现泛型,因此引用赋值之外的任何代码都无法知道分配了什么泛型参数


编辑-我不知道J7中的更改(我有点过时了:)-看起来他们解决了这个问题。

以及其他答案中描述的原因,本例中右侧的参数不需要与左侧完全相同。例如:

List<? extends Calendar> cals = new ArrayList<GregorianCalendar>();

列表从技术上讲,
不进行类型推断,它只是不检查,例如,如果您写入
列表编号=new ArrayList()正常,但列表编号=新的ArrayList(){}不是因为它需要知道创建类的实际类型。请参阅编辑。我想了解java 7之前的问题是什么,java 7迫使设计者以这种方式进行设计。
List<? extends Calendar> cals = new ArrayList<GregorianCalendar>();