为什么人们仍然在Java中使用原始类型?

时间:2022-01-04 16:26:28

Since Java 5, we've had boxing/unboxing of primitive types so that int is wrapped to be java.lang.Integer, and so and and so forth.

从Java 5开始,我们就有了原始类型的装箱/拆箱,所以int被包装成Java .lang。整数,等等。

I see a lot of new Java projects lately (that definitely require a JRE of at least version 5, if not 6) that are using int rather than java.lang.Integer, though it's much more convenient to use the latter, as it has a few helper methods for converting to long values et al.

我最近看到很多新的Java项目(如果不是6的话,肯定需要至少版本5的JRE)使用int而不是Java .lang。整数,虽然使用后者要方便得多,因为它有一些辅助方法用于转换为长值等。

Why do some still use primitive types in Java? Is there any tangible benefit?

为什么有些人仍然在Java中使用原始类型?有什么切实的好处吗?

19 个解决方案

#1


337  

In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:

在Joshua Bloch的有效Java中,第5项:“避免创建不必要的对象”,他发布了以下代码示例:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... If that's any indication why we use primitives.

而这需要43秒的时间。长时间进入原语会把时间缩短到6.8秒……如果这是我们使用原语的原因。

The lack of native value equality is also a concern (.equals() is fairly verbose compared to ==)

缺少本机值相等也是一个问题(.equals()与==相比相当冗长)

for biziclop:

biziclop:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Results in:

结果:

false
false
true
false

EDITWhy does (3) return true and (4) return false?

编辑为什么(3)返回真(4)返回假?

Because they are two different objects. The 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, though, they aren't cached, so a new object is created. To make things more complicated, the JLS demands that at least 256 flyweights be cached. JVM implementers may add more if they desire, meaning this could run on a system where the nearest 1024 are cached and all of them return true... #awkward

因为它们是两个不同的物体。最接近于0的256个整数[-128];JVM缓存它们,所以它们返回相同的对象。但是,在此范围之外,它们没有被缓存,因此创建了一个新对象。为了使事情更复杂,JLS要求至少缓存256次flyweight。如果JVM实现者愿意的话,可以添加更多的内容,这意味着可以在缓存最近的1024的系统上运行,并且它们都返回true……#尴尬

#2


75  

Autounboxing can lead to hard to spot NPEs

自动装箱会导致很难发现NPEs

Integer in = null;
...
...
int i = in; // NPE at runtime

In most situations the null assignment to in is a lot less obvious than above.

在大多数情况下,对In的零赋值比上面的要明显得多。

#3


39  

Primitive types:

基本类型:

int x = 1000;
int y = 1000;

Now evaluate:

现在评估:

x == y

It's true. Hardly surprising. Now try the boxed types:

这是真的。为奇。现在试试盒装的类型:

Integer x = 1000;
Integer y = 1000;

Now evaluate:

现在评估:

x == y

It's false. Probably. Depends on the runtime. Is that reason enough?

这是错误的。可能。依赖于运行时。这是足够的理由吗?

#4


36  

Boxed types have poorer performance and require more memory.

装箱类型的性能较差,需要更多的内存。

#5


34  

Besides performance and memory issues, I'd like to come up with another issue: The List interface would be broken without int.
The problem is the overloaded remove() method (remove(int) vs. remove(Object)). remove(Integer) would always resolve to calling the latter, so you could not remove an element by index.

除了性能和内存问题之外,我还想提出另一个问题:如果没有int,列表接口将被破坏。remove(Integer)总是决定调用后者,因此不能通过索引删除元素。

On the other hand, there is a pitfall when trying to add and remove an int:

另一方面,在添加和删除int时也会有一个陷阱:

final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!

#6


27  

Can you really imagine a

你能想象a吗

  for (int i=0; i<10000; i++) {
      do something
  }

loop with java.lang.Integer instead? A java.lang.Integer is immutable, so each increment round the loop would create a new java object on the heap, rather than just increment the int on the stack with a single JVM instruction. The performance would be diabolical.

循环. lang。整数呢?. lang。Integer是不可变的,因此循环的每一次增量都将在堆上创建一个新的java对象,而不是仅仅使用单个JVM指令增加堆栈上的int。表演将是恶魔般的。

I would really disagree that it's much mode convenient to use java.lang.Integer than int. On the contrary. Autoboxing means that you can use int where you would otherwise be forced to use Integer, and the java compiler takes care of inserting the code to create the new Integer object for you. Autoboxing is all about allowing you to use an int where an Integer is expected, with the compiler inserting the relevant object construction. It in no way removes or reduces the need for the int in the first place. With autoboxing you get the best of both worlds. You get an Integer created for you automatically when you need a heap based java object, and you get the speed and efficiency of an int when you are just doing arithmetic and local calculations.

我真的不同意使用java.lang很方便。整数比整数,相反。自动装箱意味着您可以使用int,否则您将*使用Integer, java编译器将负责插入代码,为您创建新的Integer对象。自动装箱是关于允许您使用一个整数的整数,而编译器插入相关的对象构造。它不会首先删除或减少对int的需求。有了自动装箱,你就能两全其美。当您需要一个基于堆的java对象时,您会自动为您创建一个整数,当您正在进行算术和本地计算时,您将获得int的速度和效率。

#7


17  

Primitive types are much faster:

原始类型要快得多:

int i;
i++;

Integer (all Numbers and also a String) is an immutable type: once created it can not be changed. If i was Integer, than i++ would create a new Integer object - much more expensive in terms of memory and processor.

整数(所有数字和字符串)是不可变类型:一旦创建,就不能更改它。如果我是整数,那么i++ +将创建一个新的整数对象——在内存和处理器方面要昂贵得多。

#8


15  

First and foremost, habit. If you've coded in Java for eight years, you accumulate a considerable amount of inertia. Why change if there is no compelling reason to do so? It's not as if using boxed primitives comes with any extra advantages.

首先,习惯。如果您已经用Java编写了8年,那么您将积累大量的惰性。如果没有令人信服的理由,为什么要改变呢?这并不是说使用盒装原语有什么额外的好处。

The other reason is to assert that null is not a valid option. It would be pointless and misleading to declare the sum of two numbers or a loop variable as Integer.

另一个原因是断言null不是一个有效的选项。将两个数字或循环变量的和声明为整数是没有意义的,并且会产生误导。

There's the performance aspect of it too, while the performance difference isn't critical in many cases (though when it is, it's pretty bad), nobody likes to write code that could be written just as easily in a faster way we're already used to.

它也有性能方面的问题,虽然性能差异在很多情况下并不重要(尽管当它存在的时候,它是很糟糕的),但是没有人喜欢用我们已经习惯的更快的方式编写代码。

#9


12  

By the way, Smalltalk has only objects (no primitives), and yet they had optimized their small integers (using not all 32 bits, only 27 or such) to not allocate any heap space, but simply use a special bit pattern. Also other common objects (true, false, null) had special bit patterns here.

顺便说一下,Smalltalk只有对象(没有基元),但是它们优化了它们的小整数(不是使用所有32位,只有27位),从而不分配任何堆空间,而只是使用一个特殊的位模式。其他常见对象(true、false、null)在这里也有特殊的位模式。

So, at least on 64-bit JVMs (with a 64 bit pointer namespace) it should be possible to not have any objects of Integer, Character, Byte, Short, Boolean, Float (and small Long) at all (apart from these created by explicit new ...()), only special bit patterns, which could be manipulated by the normal operators quite efficiently.

如此,至少在64位jvm(64位指针名称空间),应该有可能没有任何对象的整数、字符,字节,短,布尔,浮子(和小长)(除了这些显式创建的新…()),只有特殊的二进制模式,可以被正常的运营商很有效。

#10


9  

I can't believe no one has mentioned what I think is the most important reason: "int" is so, so much easier to type than "Integer". I think people underestimate the importance of a concise syntax. Performance isn't really a reason to avoid them because most of the time when one is using numbers is in loop indexes, and incrementing and comparing those costs nothing in any non-trivial loop (whether you're using int or Integer).

我无法相信没有人提到我认为最重要的原因:“int”比“Integer”更容易输入。我认为人们低估了简洁语法的重要性。性能并不是避免它们的真正原因,因为在使用数字时,大多数时候都是在循环索引中,在任何非平凡循环中(无论使用int还是Integer)递增和比较这些值都不需要任何代价。

The other given reason was that you can get NPEs but that's extremely easy to avoid with boxed types (and it is guaranteed to be avoided as long as you always initialize them to non-null values).

另一个给定的原因是,您可以获得NPEs,但是使用装箱类型非常容易避免(只要始终将它们初始化为非空值,就可以确保避免这种情况)。

The other reason was that (new Long(1000))==(new Long(1000)) is false, but that's just another way of saying that ".equals" has no syntactic support for boxed types (unlike the operators <, >, =, etc), so we come back to the "simpler syntax" reason.

另一个原因是(new Long(1000))= (new Long()))是假的,但这只是另一种说法”。equals”对于装箱类型没有语法支持(不像操作符<、>、=等),因此我们回到“更简单的语法”的原因。

I think Steve Yegge's non-primitive loop example illustrates my point very well: http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

我认为Steve Yegge的非原始循环示例很好地说明了我的观点:http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

Think about this: how often do you use function types in languages that have good syntax for them (like any functional language, python, ruby, and even C) compared to java where you have to simulate them using interfaces such as Runnable and Callable and nameless classes.

考虑一下这个问题:您在语言中使用函数类型的频率(如任何函数语言、python、ruby,甚至C)与java相比,您必须使用诸如Runnable、Callable和nameless类等接口来模拟它们。

#11


8  

Couple of reasons not to get rid of primitives:

不抛弃原语的几个原因:

  • Backwards compatability.
  • 向后兼容。

If it's eliminated, any old programs wouldn't even run.

如果它被删除,任何旧的程序都不会运行。

  • JVM rewrite.
  • JVM重写。

The entire JVM would have to be rewritten to support this new thing.

为了支持这个新东西,必须重写整个JVM。

  • Larger memory footprint.
  • 更大的内存占用。

You'd need to store the value and the reference, which uses more memory. If you have a huge array of bytes, using byte's is significantly smaller than using Byte's.

您需要存储值和引用,这将使用更多的内存。如果你有一个庞大的字节数组,使用字节比使用字节要小得多。

  • Null pointer issues.
  • 空指针的问题。

Declaring int i then doing stuff with i would result in no issues, but declaring Integer i and then doing the same would result in an NPE.

声明int i然后对i进行处理不会导致任何问题,但是声明Integer i然后执行相同的操作会导致NPE。

  • Equality issues.
  • 平等问题。

Consider this code:

考虑这段代码:

Integer i1 = 5;
Integer i2 = 5;

i1 == i2; // Currently would be false.

Would be false. Operators would have to be overloaded, and that would result in a major rewrite of stuff.

会是假的。操作符必须重载,这将导致大量重写。

  • Slow

Object wrappers are significantly slower than their primitive counterparts.

对象包装器比原始包装器慢得多。

#12


7  

In addition to what others have said, primitive local variables are not allocated from the heap, but instead on the stack. But objects are allocated from the heap and thus have to be garbage collected.

除了其他人所说的之外,原始的局部变量不是从堆中分配的,而是在堆栈上分配的。但是对象是从堆中分配的,因此必须进行垃圾收集。

#13


6  

Objects are much more heavyweight than primitive types, so primitive types are much more efficient than instances of wrapper classes.

对象比原始类型要重要得多,所以原始类型比包装类的实例要高效得多。

Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly. An Integer object is a complete object, which (like any object) has to be stored on the heap, and can only be accessed via a reference (pointer) to it. It most likely also takes up more than 32 bits (4 bytes) of memory.

原始类型非常简单:例如,int是32位,在内存中正好占用32位,可以直接操作。整数对象是一个完整的对象,它(与任何对象一样)必须存储在堆中,并且只能通过指向它的引用(指针)进行访问。它也很可能占用超过32位(4字节)的内存。

That said, the fact that Java has a distinction between primitive and non-primitive types is also a sign of age of the Java programming language. Newer programming languages don't have this distinction; the compiler of such a language is smart enough to figure out by itself if you're using simple values or more complex objects.

也就是说,Java区分基元类型和非基元类型也是Java编程语言时代的标志。较新的编程语言没有这种区别;如果您使用的是简单的值或更复杂的对象,那么这种语言的编译器本身就足够聪明了。

For example, in Scala there are no primitive types; there is a class Int for integers, and an Int is a real object (that you can methods on etc.). When the compiler compiles your code, it uses primitive ints behind the scenes, so using an Int is just as efficient as using a primitive int in Java.

例如,在Scala中没有原始类型;有一个用于整数的类Int,而Int是一个真正的对象(您可以对其进行方法等等)。当编译器编译代码时,它会在幕后使用原始的ints,因此使用Int与在Java中使用原始Int一样有效。

#14


5  

It's hard to know what kind of optimizations are going on under the covers.

很难知道在幕后正在进行什么样的优化。

For local use, when the compiler has enough information to make optimizations excluding the possibility of the null value, I expect the performance to be the same or similar.

对于本地使用,当编译器有足够的信息进行优化时,排除了空值的可能性,我希望性能是相同的或类似的。

However, arrays of primitives are apparently very different from collections of boxed primitives. This makes sense given that very few optimizations are possible deep within a collection.

然而,原语的数组显然与盒式原语的集合非常不同。考虑到在集合内部很少可能进行优化,这是有意义的。

Furthermore, Integer has a much higher logical overhead as compared with int: now you have to worry about about whether or not int a = b + c; throws an exception.

此外,与int相比,Integer具有更高的逻辑开销:现在您需要担心int a = b + c是否正确;将抛出一个异常。

I'd use the primitives as much as possible and rely on the factory methods and autoboxing to give me the more semantically powerful boxed types when they are needed.

我将尽可能多地使用原语,并依赖工厂方法和自动装箱,在需要时为我提供更强大的框类型。

#15


5  

int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

Milliseconds taken to loop '100000000' times around Long: 468

在很长时间内循环10000000次的毫秒数:468。

Milliseconds taken to loop '100000000' times around long: 31

循环“100000000”的毫秒数:31

On a side note, I wouldn't mind seeing something like this find it's way into Java.

顺便说一句,我不介意看到这样的东西进入Java。

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

Where the for loop automatically increments loop1 from 0 to 1000 or

for循环自动将loop1从0增加到1000

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

Where the for loop automatically decrements loop1 1000 to 0.

其中for循环自动将loop1 1000减为0。

#16


5  

Primitive types have many advantages:

原始类型有很多优点:

  • Simpler code to write
  • 更简单的代码编写
  • Performance is better since you are not instantiating an object for the variable
  • 性能更好,因为您没有为变量实例化对象
  • Since they do not represent a reference to an object there is no need to check for nulls
  • 因为它们不代表对象的引用,所以不需要检查null
  • Use primitive types unless you need to take advantage of the boxing features.
  • 使用基本类型,除非您需要利用装箱特性。

#17


2  

I agree with previous answers, using primitives wrapper objects can be expensive. But, if performance is not critical in your application, you avoid overflows when using objects. For example:

我同意前面的回答,使用原语包装器对象可能很昂贵。但是,如果性能在应用程序中并不重要,那么在使用对象时可以避免溢出。例如:

long bigNumber = Integer.MAX_VALUE + 2;

The value of bigNumber is -2147483647, and you would expect it to be 2147483649. It's a bug in the code that would be fixed by doing:

bigNumber的值是-2147483647,应该是2147483649。这是代码中的一个漏洞,可以通过以下操作来修复:

long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now.

And bigNumber would be 2147483649. These kind of bugs sometimes are easy to be missed and can lead to unknown behavior or vulnerabilities (see CWE-190).

大数字是2147483649。这些bug有时很容易被忽略,并可能导致未知的行为或漏洞(参见CWE-190)。

If you use wrapper objects, the equivalent code won't compile.

如果您使用包装器对象,等效的代码将不会编译。

Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling

So it's easier to stop these kind of issues by using primitives wrapper objects.

因此,使用原语包装器对象可以更容易地阻止此类问题。

Your question is so answered already, that I reply just to add a little bit more information not mentioned before.

你的问题已经回答得很好了,我的回复只是添加了一些之前没有提到过的信息。

#18


1  

  1. You need primitives for doing mathematical operations
  2. 进行数学运算需要基本类型
  3. Primitives takes less memory as answered above and better performing
  4. 原语需要较少的内存,就像上面回答的那样,表现更好。

You should ask why Class/Object type is required

您应该问为什么需要类/对象类型

Reason for having Object type is to make our life easier when we deal with Collections. Primitives cannot be added directly to List/Map rather you need to write a wrapper class. Readymade Integer kind of Classes helps you here plus it has many utility methods like Integer.pareseInt(str)

拥有对象类型的原因是在处理集合时使我们的生活更容易。原语不能直接添加到列表/映射,而需要编写一个包装类。Readymade Integer类型的类帮助你在这里加上它有很多实用方法比如Integer.pareseInt(str)

#19


0  

Because JAVA performs all mathematical operations in primitive types. Consider this example:

因为JAVA在基本类型中执行所有的数学操作。考虑一下这个例子:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i: li)
        if (i % 2 == 0)
            sum += i;
        return sum;
}

Here, reminder and unary plus operations can not be applied on Integer(Reference) type, compiler performs unboxing and do the operations.

在这里,提醒和一元加操作不能应用于整数(引用)类型,编译器执行开箱和操作。

So, make sure how many autoboxing and unboxing operations happen in java program. Since, It takes time to perform this operations.

因此,请确保在java程序中发生了多少自动装箱和反装箱操作。因为执行此操作需要时间。

Generally, it is better to keep arguments of type Reference and result of primitive type.

通常,最好保留类型引用的参数和原始类型的结果。

#1


337  

In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:

在Joshua Bloch的有效Java中,第5项:“避免创建不必要的对象”,他发布了以下代码示例:

public static void main(String[] args) {
    Long sum = 0L; // uses Long, not long
    for (long i = 0; i <= Integer.MAX_VALUE; i++) {
        sum += i;
    }
    System.out.println(sum);
}

and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... If that's any indication why we use primitives.

而这需要43秒的时间。长时间进入原语会把时间缩短到6.8秒……如果这是我们使用原语的原因。

The lack of native value equality is also a concern (.equals() is fairly verbose compared to ==)

缺少本机值相等也是一个问题(.equals()与==相比相当冗长)

for biziclop:

biziclop:

class Biziclop {

    public static void main(String[] args) {
        System.out.println(new Integer(5) == new Integer(5));
        System.out.println(new Integer(500) == new Integer(500));

        System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
        System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
    }
}

Results in:

结果:

false
false
true
false

EDITWhy does (3) return true and (4) return false?

编辑为什么(3)返回真(4)返回假?

Because they are two different objects. The 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, though, they aren't cached, so a new object is created. To make things more complicated, the JLS demands that at least 256 flyweights be cached. JVM implementers may add more if they desire, meaning this could run on a system where the nearest 1024 are cached and all of them return true... #awkward

因为它们是两个不同的物体。最接近于0的256个整数[-128];JVM缓存它们,所以它们返回相同的对象。但是,在此范围之外,它们没有被缓存,因此创建了一个新对象。为了使事情更复杂,JLS要求至少缓存256次flyweight。如果JVM实现者愿意的话,可以添加更多的内容,这意味着可以在缓存最近的1024的系统上运行,并且它们都返回true……#尴尬

#2


75  

Autounboxing can lead to hard to spot NPEs

自动装箱会导致很难发现NPEs

Integer in = null;
...
...
int i = in; // NPE at runtime

In most situations the null assignment to in is a lot less obvious than above.

在大多数情况下,对In的零赋值比上面的要明显得多。

#3


39  

Primitive types:

基本类型:

int x = 1000;
int y = 1000;

Now evaluate:

现在评估:

x == y

It's true. Hardly surprising. Now try the boxed types:

这是真的。为奇。现在试试盒装的类型:

Integer x = 1000;
Integer y = 1000;

Now evaluate:

现在评估:

x == y

It's false. Probably. Depends on the runtime. Is that reason enough?

这是错误的。可能。依赖于运行时。这是足够的理由吗?

#4


36  

Boxed types have poorer performance and require more memory.

装箱类型的性能较差,需要更多的内存。

#5


34  

Besides performance and memory issues, I'd like to come up with another issue: The List interface would be broken without int.
The problem is the overloaded remove() method (remove(int) vs. remove(Object)). remove(Integer) would always resolve to calling the latter, so you could not remove an element by index.

除了性能和内存问题之外,我还想提出另一个问题:如果没有int,列表接口将被破坏。remove(Integer)总是决定调用后者,因此不能通过索引删除元素。

On the other hand, there is a pitfall when trying to add and remove an int:

另一方面,在添加和删除int时也会有一个陷阱:

final int i = 42;
final List<Integer> list = new ArrayList<Integer>();
list.add(i); // add(Object)
list.remove(i); // remove(int) - Ouch!

#6


27  

Can you really imagine a

你能想象a吗

  for (int i=0; i<10000; i++) {
      do something
  }

loop with java.lang.Integer instead? A java.lang.Integer is immutable, so each increment round the loop would create a new java object on the heap, rather than just increment the int on the stack with a single JVM instruction. The performance would be diabolical.

循环. lang。整数呢?. lang。Integer是不可变的,因此循环的每一次增量都将在堆上创建一个新的java对象,而不是仅仅使用单个JVM指令增加堆栈上的int。表演将是恶魔般的。

I would really disagree that it's much mode convenient to use java.lang.Integer than int. On the contrary. Autoboxing means that you can use int where you would otherwise be forced to use Integer, and the java compiler takes care of inserting the code to create the new Integer object for you. Autoboxing is all about allowing you to use an int where an Integer is expected, with the compiler inserting the relevant object construction. It in no way removes or reduces the need for the int in the first place. With autoboxing you get the best of both worlds. You get an Integer created for you automatically when you need a heap based java object, and you get the speed and efficiency of an int when you are just doing arithmetic and local calculations.

我真的不同意使用java.lang很方便。整数比整数,相反。自动装箱意味着您可以使用int,否则您将*使用Integer, java编译器将负责插入代码,为您创建新的Integer对象。自动装箱是关于允许您使用一个整数的整数,而编译器插入相关的对象构造。它不会首先删除或减少对int的需求。有了自动装箱,你就能两全其美。当您需要一个基于堆的java对象时,您会自动为您创建一个整数,当您正在进行算术和本地计算时,您将获得int的速度和效率。

#7


17  

Primitive types are much faster:

原始类型要快得多:

int i;
i++;

Integer (all Numbers and also a String) is an immutable type: once created it can not be changed. If i was Integer, than i++ would create a new Integer object - much more expensive in terms of memory and processor.

整数(所有数字和字符串)是不可变类型:一旦创建,就不能更改它。如果我是整数,那么i++ +将创建一个新的整数对象——在内存和处理器方面要昂贵得多。

#8


15  

First and foremost, habit. If you've coded in Java for eight years, you accumulate a considerable amount of inertia. Why change if there is no compelling reason to do so? It's not as if using boxed primitives comes with any extra advantages.

首先,习惯。如果您已经用Java编写了8年,那么您将积累大量的惰性。如果没有令人信服的理由,为什么要改变呢?这并不是说使用盒装原语有什么额外的好处。

The other reason is to assert that null is not a valid option. It would be pointless and misleading to declare the sum of two numbers or a loop variable as Integer.

另一个原因是断言null不是一个有效的选项。将两个数字或循环变量的和声明为整数是没有意义的,并且会产生误导。

There's the performance aspect of it too, while the performance difference isn't critical in many cases (though when it is, it's pretty bad), nobody likes to write code that could be written just as easily in a faster way we're already used to.

它也有性能方面的问题,虽然性能差异在很多情况下并不重要(尽管当它存在的时候,它是很糟糕的),但是没有人喜欢用我们已经习惯的更快的方式编写代码。

#9


12  

By the way, Smalltalk has only objects (no primitives), and yet they had optimized their small integers (using not all 32 bits, only 27 or such) to not allocate any heap space, but simply use a special bit pattern. Also other common objects (true, false, null) had special bit patterns here.

顺便说一下,Smalltalk只有对象(没有基元),但是它们优化了它们的小整数(不是使用所有32位,只有27位),从而不分配任何堆空间,而只是使用一个特殊的位模式。其他常见对象(true、false、null)在这里也有特殊的位模式。

So, at least on 64-bit JVMs (with a 64 bit pointer namespace) it should be possible to not have any objects of Integer, Character, Byte, Short, Boolean, Float (and small Long) at all (apart from these created by explicit new ...()), only special bit patterns, which could be manipulated by the normal operators quite efficiently.

如此,至少在64位jvm(64位指针名称空间),应该有可能没有任何对象的整数、字符,字节,短,布尔,浮子(和小长)(除了这些显式创建的新…()),只有特殊的二进制模式,可以被正常的运营商很有效。

#10


9  

I can't believe no one has mentioned what I think is the most important reason: "int" is so, so much easier to type than "Integer". I think people underestimate the importance of a concise syntax. Performance isn't really a reason to avoid them because most of the time when one is using numbers is in loop indexes, and incrementing and comparing those costs nothing in any non-trivial loop (whether you're using int or Integer).

我无法相信没有人提到我认为最重要的原因:“int”比“Integer”更容易输入。我认为人们低估了简洁语法的重要性。性能并不是避免它们的真正原因,因为在使用数字时,大多数时候都是在循环索引中,在任何非平凡循环中(无论使用int还是Integer)递增和比较这些值都不需要任何代价。

The other given reason was that you can get NPEs but that's extremely easy to avoid with boxed types (and it is guaranteed to be avoided as long as you always initialize them to non-null values).

另一个给定的原因是,您可以获得NPEs,但是使用装箱类型非常容易避免(只要始终将它们初始化为非空值,就可以确保避免这种情况)。

The other reason was that (new Long(1000))==(new Long(1000)) is false, but that's just another way of saying that ".equals" has no syntactic support for boxed types (unlike the operators <, >, =, etc), so we come back to the "simpler syntax" reason.

另一个原因是(new Long(1000))= (new Long()))是假的,但这只是另一种说法”。equals”对于装箱类型没有语法支持(不像操作符<、>、=等),因此我们回到“更简单的语法”的原因。

I think Steve Yegge's non-primitive loop example illustrates my point very well: http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

我认为Steve Yegge的非原始循环示例很好地说明了我的观点:http://sites.google.com/site/steveyegge2/language-trickery-and-ejb

Think about this: how often do you use function types in languages that have good syntax for them (like any functional language, python, ruby, and even C) compared to java where you have to simulate them using interfaces such as Runnable and Callable and nameless classes.

考虑一下这个问题:您在语言中使用函数类型的频率(如任何函数语言、python、ruby,甚至C)与java相比,您必须使用诸如Runnable、Callable和nameless类等接口来模拟它们。

#11


8  

Couple of reasons not to get rid of primitives:

不抛弃原语的几个原因:

  • Backwards compatability.
  • 向后兼容。

If it's eliminated, any old programs wouldn't even run.

如果它被删除,任何旧的程序都不会运行。

  • JVM rewrite.
  • JVM重写。

The entire JVM would have to be rewritten to support this new thing.

为了支持这个新东西,必须重写整个JVM。

  • Larger memory footprint.
  • 更大的内存占用。

You'd need to store the value and the reference, which uses more memory. If you have a huge array of bytes, using byte's is significantly smaller than using Byte's.

您需要存储值和引用,这将使用更多的内存。如果你有一个庞大的字节数组,使用字节比使用字节要小得多。

  • Null pointer issues.
  • 空指针的问题。

Declaring int i then doing stuff with i would result in no issues, but declaring Integer i and then doing the same would result in an NPE.

声明int i然后对i进行处理不会导致任何问题,但是声明Integer i然后执行相同的操作会导致NPE。

  • Equality issues.
  • 平等问题。

Consider this code:

考虑这段代码:

Integer i1 = 5;
Integer i2 = 5;

i1 == i2; // Currently would be false.

Would be false. Operators would have to be overloaded, and that would result in a major rewrite of stuff.

会是假的。操作符必须重载,这将导致大量重写。

  • Slow

Object wrappers are significantly slower than their primitive counterparts.

对象包装器比原始包装器慢得多。

#12


7  

In addition to what others have said, primitive local variables are not allocated from the heap, but instead on the stack. But objects are allocated from the heap and thus have to be garbage collected.

除了其他人所说的之外,原始的局部变量不是从堆中分配的,而是在堆栈上分配的。但是对象是从堆中分配的,因此必须进行垃圾收集。

#13


6  

Objects are much more heavyweight than primitive types, so primitive types are much more efficient than instances of wrapper classes.

对象比原始类型要重要得多,所以原始类型比包装类的实例要高效得多。

Primitive types are very simple: for example an int is 32 bits and takes up exactly 32 bits in memory, and can be manipulated directly. An Integer object is a complete object, which (like any object) has to be stored on the heap, and can only be accessed via a reference (pointer) to it. It most likely also takes up more than 32 bits (4 bytes) of memory.

原始类型非常简单:例如,int是32位,在内存中正好占用32位,可以直接操作。整数对象是一个完整的对象,它(与任何对象一样)必须存储在堆中,并且只能通过指向它的引用(指针)进行访问。它也很可能占用超过32位(4字节)的内存。

That said, the fact that Java has a distinction between primitive and non-primitive types is also a sign of age of the Java programming language. Newer programming languages don't have this distinction; the compiler of such a language is smart enough to figure out by itself if you're using simple values or more complex objects.

也就是说,Java区分基元类型和非基元类型也是Java编程语言时代的标志。较新的编程语言没有这种区别;如果您使用的是简单的值或更复杂的对象,那么这种语言的编译器本身就足够聪明了。

For example, in Scala there are no primitive types; there is a class Int for integers, and an Int is a real object (that you can methods on etc.). When the compiler compiles your code, it uses primitive ints behind the scenes, so using an Int is just as efficient as using a primitive int in Java.

例如,在Scala中没有原始类型;有一个用于整数的类Int,而Int是一个真正的对象(您可以对其进行方法等等)。当编译器编译代码时,它会在幕后使用原始的ints,因此使用Int与在Java中使用原始Int一样有效。

#14


5  

It's hard to know what kind of optimizations are going on under the covers.

很难知道在幕后正在进行什么样的优化。

For local use, when the compiler has enough information to make optimizations excluding the possibility of the null value, I expect the performance to be the same or similar.

对于本地使用,当编译器有足够的信息进行优化时,排除了空值的可能性,我希望性能是相同的或类似的。

However, arrays of primitives are apparently very different from collections of boxed primitives. This makes sense given that very few optimizations are possible deep within a collection.

然而,原语的数组显然与盒式原语的集合非常不同。考虑到在集合内部很少可能进行优化,这是有意义的。

Furthermore, Integer has a much higher logical overhead as compared with int: now you have to worry about about whether or not int a = b + c; throws an exception.

此外,与int相比,Integer具有更高的逻辑开销:现在您需要担心int a = b + c是否正确;将抛出一个异常。

I'd use the primitives as much as possible and rely on the factory methods and autoboxing to give me the more semantically powerful boxed types when they are needed.

我将尽可能多地使用原语,并依赖工厂方法和自动装箱,在需要时为我提供更强大的框类型。

#15


5  

int loops = 100000000;

long start = System.currentTimeMillis();
for (Long l = new Long(0); l<loops;l++) {
    //System.out.println("Long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around Long: "+ (System.currentTimeMillis()- start));

start = System.currentTimeMillis();
for (long l = 0; l<loops;l++) {
    //System.out.println("long: "+l);
}
System.out.println("Milliseconds taken to loop '"+loops+"' times around long: "+ (System.currentTimeMillis()- start));

Milliseconds taken to loop '100000000' times around Long: 468

在很长时间内循环10000000次的毫秒数:468。

Milliseconds taken to loop '100000000' times around long: 31

循环“100000000”的毫秒数:31

On a side note, I wouldn't mind seeing something like this find it's way into Java.

顺便说一句,我不介意看到这样的东西进入Java。

Integer loop1 = new Integer(0);
for (loop1.lessThan(1000)) {
   ...
}

Where the for loop automatically increments loop1 from 0 to 1000 or

for循环自动将loop1从0增加到1000

Integer loop1 = new Integer(1000);
for (loop1.greaterThan(0)) {
   ...
}

Where the for loop automatically decrements loop1 1000 to 0.

其中for循环自动将loop1 1000减为0。

#16


5  

Primitive types have many advantages:

原始类型有很多优点:

  • Simpler code to write
  • 更简单的代码编写
  • Performance is better since you are not instantiating an object for the variable
  • 性能更好,因为您没有为变量实例化对象
  • Since they do not represent a reference to an object there is no need to check for nulls
  • 因为它们不代表对象的引用,所以不需要检查null
  • Use primitive types unless you need to take advantage of the boxing features.
  • 使用基本类型,除非您需要利用装箱特性。

#17


2  

I agree with previous answers, using primitives wrapper objects can be expensive. But, if performance is not critical in your application, you avoid overflows when using objects. For example:

我同意前面的回答,使用原语包装器对象可能很昂贵。但是,如果性能在应用程序中并不重要,那么在使用对象时可以避免溢出。例如:

long bigNumber = Integer.MAX_VALUE + 2;

The value of bigNumber is -2147483647, and you would expect it to be 2147483649. It's a bug in the code that would be fixed by doing:

bigNumber的值是-2147483647,应该是2147483649。这是代码中的一个漏洞,可以通过以下操作来修复:

long bigNumber = Integer.MAX_VALUE + 2l; // note that '2' is a long now.

And bigNumber would be 2147483649. These kind of bugs sometimes are easy to be missed and can lead to unknown behavior or vulnerabilities (see CWE-190).

大数字是2147483649。这些bug有时很容易被忽略,并可能导致未知的行为或漏洞(参见CWE-190)。

If you use wrapper objects, the equivalent code won't compile.

如果您使用包装器对象,等效的代码将不会编译。

Long bigNumber = Integer.MAX_VALUE + 2; // Not compiling

So it's easier to stop these kind of issues by using primitives wrapper objects.

因此,使用原语包装器对象可以更容易地阻止此类问题。

Your question is so answered already, that I reply just to add a little bit more information not mentioned before.

你的问题已经回答得很好了,我的回复只是添加了一些之前没有提到过的信息。

#18


1  

  1. You need primitives for doing mathematical operations
  2. 进行数学运算需要基本类型
  3. Primitives takes less memory as answered above and better performing
  4. 原语需要较少的内存,就像上面回答的那样,表现更好。

You should ask why Class/Object type is required

您应该问为什么需要类/对象类型

Reason for having Object type is to make our life easier when we deal with Collections. Primitives cannot be added directly to List/Map rather you need to write a wrapper class. Readymade Integer kind of Classes helps you here plus it has many utility methods like Integer.pareseInt(str)

拥有对象类型的原因是在处理集合时使我们的生活更容易。原语不能直接添加到列表/映射,而需要编写一个包装类。Readymade Integer类型的类帮助你在这里加上它有很多实用方法比如Integer.pareseInt(str)

#19


0  

Because JAVA performs all mathematical operations in primitive types. Consider this example:

因为JAVA在基本类型中执行所有的数学操作。考虑一下这个例子:

public static int sumEven(List<Integer> li) {
    int sum = 0;
    for (Integer i: li)
        if (i % 2 == 0)
            sum += i;
        return sum;
}

Here, reminder and unary plus operations can not be applied on Integer(Reference) type, compiler performs unboxing and do the operations.

在这里,提醒和一元加操作不能应用于整数(引用)类型,编译器执行开箱和操作。

So, make sure how many autoboxing and unboxing operations happen in java program. Since, It takes time to perform this operations.

因此,请确保在java程序中发生了多少自动装箱和反装箱操作。因为执行此操作需要时间。

Generally, it is better to keep arguments of type Reference and result of primitive type.

通常,最好保留类型引用的参数和原始类型的结果。