我在阅读《关于软件的更多Joel》时,偶然看到Joel Spolsky说,有一种特殊类型的程序员知道Java/ c#(面向对象编程语言)中int和Integer的区别。

那么,有什么不同呢?


当前回答

我将对上面给出的优秀答案进行补充,并讨论装箱和拆箱,以及如何将其应用于Java(尽管c#也有)。我将只使用Java术语,因为我对它更熟悉。

正如答案所提到的,int只是一个数字(称为未装箱类型),而Integer是一个对象(包含数字,因此是装箱类型)。在Java术语中,这意味着(除了不能在int上调用方法之外),您不能在集合(List, Map等)中存储int或其他非对象类型。为了存储它们,必须首先将它们装入相应的盒装类型中。

Java 5以后有了所谓的自动装箱和自动拆箱,允许装箱/拆箱在幕后完成。比较和对比:Java 5版本:

Deque<Integer> queue;

void add(int n) {
    queue.add(n);
}

int remove() {
    return queue.remove();
}

Java 1.4或更早版本(也没有泛型):

Deque queue;

void add(int n) {
    queue.add(Integer.valueOf(n));
}

int remove() {
    return ((Integer) queue.remove()).intValue();
}

必须注意的是,尽管Java 5版本很简洁,但两个版本生成的字节码是相同的。因此,尽管自动装箱和自动拆箱非常方便,因为您编写的代码更少,但这些操作确实发生在幕后,具有相同的运行时成本,因此您仍然必须知道它们的存在。

希望这能有所帮助!

其他回答

Java已经回答了这个问题,下面是c#的答案:

“Integer”在c#中不是一个有效的类型名称,“int”只是System.Int32的别名。此外,与Java(或c++)不同,c#中没有任何特殊的基本类型,c#中类型的每个实例(包括int)都是一个对象。下面是一些演示代码:

void DoStuff()
{
    System.Console.WriteLine( SomeMethod((int)5) );
    System.Console.WriteLine( GetTypeName<int>() );
}

string SomeMethod(object someParameter)
{
    return string.Format("Some text {0}", someParameter.ToString());
}

string GetTypeName<T>()
{
    return (typeof (T)).FullName;
}

在Java中,JVM有两种基本类型。1)基本类型和2)引用类型。int是基本类型,Integer是类类型(一种引用类型)。

基元值不与其他基元值共享状态。类型为基本类型的变量总是保存该类型的基本值。

int aNumber = 4;
int anotherNum = aNumber;
aNumber += 6;
System.out.println(anotherNum); // Prints 4

对象是动态创建的类实例或数组。引用值(通常只是引用)是指向这些对象的指针和一个特殊的空引用,它不引用任何对象。同一个对象可能有多个引用。

Integer aNumber = Integer.valueOf(4);
Integer anotherNumber = aNumber; // anotherNumber references the 
                                 // same object as aNumber

在Java中,所有东西都是通过值传递的。对于对象,传递的值是对象的引用。因此,java中int和Integer的另一个区别是它们在方法调用中传递的方式。例如在

public int add(int a, int b) {
    return a + b;
}
final int two = 2;
int sum = add(1, two);

变量2作为原始整数类型2传递。而在

public int add(Integer a, Integer b) {
    return a.intValue() + b.intValue();
}
final Integer two = Integer.valueOf(2);
int sum = add(Integer.valueOf(1), two);

变量two作为一个引用传递给一个保存整数值2的对象。


@WolfmanDragon: 通过引用传递将像这样工作:

public void increment(int x) {
  x = x + 1;
}
int a = 1;
increment(a);
// a is now 2

当increment函数被调用时,它传递一个指向变量a的引用(指针),并且increment函数直接修改变量a。

对于对象类型,它的工作方式如下:

public void increment(Integer x) {
  x = Integer.valueOf(x.intValue() + 1);
}
Integer a = Integer.valueOf(1);
increment(a);
// a is now 2

现在你看到区别了吗?

(Java版本) 简单来说,int是原始的(不能有空值),Integer是int的包装对象。

一个使用Integer和int的例子,当你想比较int变量时,它会抛出错误。

int a;
//assuming a value you are getting from data base which is null
if(a ==null) // this is wrong - cannot compare primitive to null
{
do something...}

Instead you will use,
Integer a;
//assuming a value you are getting from data base which is null
if(a ==null) // this is correct/legal
{ do something...}

01. 整数可以为空。但是int不能为null。

Integer value1 = null; //OK

int value2 = null      //Error

02. 只能将包装器类类型值传递给任何集合类。

(包装类-布尔,字符,字节,短,整数,长,浮动,双)

List<Integer> element = new ArrayList<>();
int valueInt = 10;
Integer  valueInteger = new Integer(value);
element.add(valueInteger);

但通常我们在集合类中添加原始值?02点正确吗?

List<Integer> element = new ArrayList<>();
element.add(5);

是的02是正确的,因为自动装箱。

自动装箱是java编译器进行的自动转换 原始类型与其对应的包装器类之间。

然后5转换为整型值自动装箱。

在Java中,'int'类型是一个原语,而'Integer'类型是一个对象。

在c#中,'int'类型与System相同。Int32,是一个值类型(即更像java 'int')。整数(就像任何其他值类型一样)可以被装箱(“包装”)到一个对象中。


对象和原语之间的区别在某种程度上超出了这个问题的范围,但总结一下:

对象为多态性提供了便利,通过引用传递(或者更准确地说,通过值传递引用),并从堆中分配。相反,原语是按值传递的不可变类型,通常从堆栈中分配。