繁体   English   中英

为什么Java Collections不能直接存储Primitives类型?

[英]Why can Java Collections not directly store Primitives types?

Java集合只存储对象,而不是基本类型; 但是我们可以存储包装类。

为什么这个约束?

这是一个Java设计决策,有些人认为是错误的。 容器需要对象和基元不是从Object派生的。

这是.NET设计人员从JVM学到的一个地方,并实现了值类型和泛型,以便在许多情况下消除拳击。 在CLR中,通用容器可以将值类型存储为底层容器结构的一部分。

Java选择在没有JVM支持的情况下在编译器中100%添加泛型支持。 JVM就是这样,不支持“非对象”对象。 Java泛型允许你假装没有包装器,但你仍然支付拳击的性能价格。 这对于某些类程序来说非常重要。

拳击是一种技术妥协,我觉得这是实施细节渗透到语言中。 Autoboxing是很好的语法糖,但仍然是性能损失。 如果有的话,我希望编译器在自动装箱时警告我。 (据我所知,现在可能,我在2010年写了这个答案)。

关于拳击的一个很好的解释: 为什么有些语言需要拳击和拆箱?

对Java泛型的批评: 为什么有人声称Java的泛型实现很糟糕?

在Java的辩护中,很容易回顾和批评。 JVM经受住了时间的考验,在很多方面都是一个很好的设计。

使实施更容易。 由于Java基元不被视为对象,因此您需要为每个基元创建单独的集合类(无需共享的模板代码)。

你可以这样做,当然,只需看看GNU TroveApache Commons PrimitivesHPPC

除非你有非常大的集合,否则包装器的开销对于人们来说并不重要(当你确实拥有非常大的原始集合时,你可能需要花费精力来研究为它们使用/构建专用数据结构)。

这是两个事实的组合:

  • Java原始类型不是引用类型(例如, int不是Object
  • Java使用类型擦除引用类型来进行泛型(例如, List<?> List<Object>在运行时实际上是List<Object>

由于这两者都是正确的,因此通用Java集合无法直接存储基本类型。 为方便起见,引入了自动装箱以允许原始类型自动装箱作为参考类型。 不过不要误会,集合仍然存储对象引用,无论如何。

这可以避免吗? 也许。

  • 如果intObject ,则根本不需要框类型。
  • 如果没有使用类型擦除来完成泛型,那么原语可以用于类型参数。

自动装箱和自动拆箱的概念。 如果尝试在List<Integer>存储int ,Java编译器将自动将其转换为Integer

它真的不是一个约束吗?

考虑是否要创建存储原始值的集合。 你会如何编写一个可以存储int,float或char的集合? 最有可能你最终会有多个集合,所以你需要一个intlist和一个charlist等。

在编写集合类时,利用Java的面向对象特性,它可以存储任何对象,因此您只需要一个集合类。 这种多态性的想法非常强大,大大简化了库的设计。

我想我们可能会在JDK中看到这个空间的进展可能在基于这个JEP的Java 10中 - http://openjdk.java.net/jeps/218

如果你想在今天的集合中避免使用拳击原语,那么有几种第三方选择。 除了前面提到的第三方选项之外,还有Eclipse CollectionsFastUtilKoloboke

之前还发布了原始地图的比较,标题为:大型HashMap概述: JDK,FastUtil,Goldman Sachs,HPPC,Koloboke,Trove GS Collections(Goldman Sachs)库已迁移到Eclipse Foundation,现在是Eclipse Collections。

主要原因是java设计策略。 ++ 1)集合需要对象进行操作,而基元不是从对象派生的,因此这可能是另一个原因。 2)Java原始数据类型不是ex的引用类型。 int不是对象。

克服: -

我们有自动装箱和自动拆箱的概念。 因此,如果您尝试存储原始数据类型,编译器将自动将其转换为该原始数据类的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM