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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2504959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:35:28  来源:igfitidea点击:

Why can Java Collections not directly store Primitives types?

javacollectionstypesprimitive-types

提问by JavaUser

Java collections only store Objects, not primitive types; however we can store the wrapper classes.

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

Why this constraint?

为什么有这个约束?

采纳答案by codenheim

It was a Java design decision, and one that some consider a mistake. Containers want Objects and primitives don't derive from Object.

这是一个 Java 设计决定,有些人认为这是一个错误。容器需要对象,而原语不是从对象派生的。

This is one place that .NET designers learned from the JVM and implemented value types and generics such that boxing is eliminated in many cases. In CLR, generic containers can store value types as part of the underlying container structure.

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

Java opted to add generic support 100% in the compiler without support from the JVM. The JVM being what it is, doesn't support a "non-object" object. Java generics allow you to pretend there is no wrapper, but you still pay the performance price of boxing. This is IMPORTANT for certain classes of programs.

Java 选择在没有 JVM 支持的情况下在编译器中添加 100% 的通用支持。JVM 不支持“非对象”对象。Java 泛型允许您假装没有包装器,但您仍然要为拳击的性能付出代价。这对于某些类别的程序很重要。

Boxing is a technical compromise, and I feel it is implementation detail leaking into the language. Autoboxing is nice syntactic sugar, but is still a performance penalty. If anything, I'd like the compiler to warn me when it autoboxes. (For all I know, it may now, I wrote this answer in 2010).

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

A good explanation on SO about boxing: Why do some languages need Boxing and Unboxing?

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

And criticism of Java generics: Why do some claim that Java's implementation of generics is bad?

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

In Java's defense, it is easy to look backwards and criticize. The JVM has withstood the test of time, and is a good design in many respects.

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

回答by Jeremy

There is the concept of auto-boxingand auto-unboxing. If you attempt to store an intin a List<Integer>the Java compiler will automatically convert it to an Integer.

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

回答by Vincent Ramdhanie

Its not really a constraint is it?

它不是真正的约束吗?

Consider if you wanted to create a collection that stored primitive values. How would you write a collection that can store either int, or float or char? Most likely you will end up with multiple collections, so you will need an intlist and a charlist etc.

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

Taking advantage of the object oriented nature of Java when you write a collection class it can store any object so you need only one collection class. This idea, polymorphism, is very powerful and greatly simplifies the design of libraries.

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

回答by polygenelubricants

It's a combination of two facts:

这是两个事实的结合:

  • Java primitive types are not reference types (e.g. an intis not an Object)
  • Java does generics using type-erasure of reference types (e.g. a List<?>is really a List<Object>at run-time)
  • Java 原始类型不是引用类型(例如 anint不是 an Object
  • Java 使用引用类型的类型擦除来执行泛型(例如List<?>aList<Object>在运行时实际上是 a )

Since both of these are true, generic Java collections can not store primitive types directly. For convenience, autoboxing is introduced to allow primitive types to be automatically boxed as reference types. Make no mistake about it, though, the collections are still storing object references regardless.

由于这两个都是正确的,泛型 Java 集合不能直接存储原始类型。为方便起见,引入了自动装箱以允许将基本类型自动装箱为引用类型。毫无疑问,无论如何,集合仍然存储对象引用。

Could this have been avoided? Perhaps.

这本来可以避免吗?也许。

  • If an intis an Object, then there's no need for box types at all.
  • If generics aren't done using type-erasure, then primitives could've been used for type parameters.
  • 如果 anint是 an Object,则根本不需要框类型。
  • 如果泛型不是使用类型擦除完成的,那么原语就可以用于类型参数。

回答by Thilo

Makes the implementation easier. Since Java primitives are not considered Objects, you would need to create a separate collection class for each of these primitives (no template code to share).

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

You can do that, of course, just see GNU Trove, Apache Commons Primitivesor HPPC.

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

Unless you have really large collections, the overhead for the wrappers does not matter enough for people to care (and when you do have really large primitive collections, you might want to spend the effort to look at using/building a specialized data structure for them).

除非您有非常大的集合,否则包装器的开销不足以让人们关心(并且当您确实有非常大的原始集合时,您可能想要花精力为它们使用/构建专门的数据结构)。

回答by Donald Raab

I think we might see progress in this space in the JDK possibly in Java 10 based on this JEP - http://openjdk.java.net/jeps/218.

我认为我们可能会在基于此 JEP - http://openjdk.java.net/jeps/218 的Java 10 中看到 JDK 在这个领域的进展。

If you want to avoid boxing primitives in collections today, there are several third party alternatives. In addition to the previously mentioned third party options there is also Eclipse Collections, FastUtiland Koloboke.

如果您今天想避免在集合中装箱原语,有几种第三方替代方案。除了前面提到的第三方选项之外,还有Eclipse CollectionsFastUtilKoloboke

A comparison of primitive maps was also published a while ago with the title: Large HashMap overview: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove. The GS Collections (Goldman Sachs) library was migrated to the Eclipse Foundation and is now Eclipse Collections.

前阵子还发布了一个原始映射的比较,标题为:Large HashMap 概述:JDK、FastUtil、Goldman Sachs、HPPC、Koloboke、Trove。GS Collections (Goldman Sachs) 库已迁移到 Eclipse Foundation,现在更名为 Eclipse Collections。

回答by user5693566

The main reason is the java design strategy. ++ 1) collections requires objects for manipulation and primitives are not derived from object so this can be the other reason. 2) Java primitive data types are not reference type for ex. int is not an object.

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

To Overcome:-

克服:-

we have concept of auto-boxing and auto-unboxing. so if you are trying to store primitive data types compiler will automatically convert that into object of that primitive data class.

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