Java和C#中的int和Integer有什么区别?

时间:2020-03-05 18:37:22  来源:igfitidea点击:

当我遇到Joel Spolsky时,我正在阅读《更多关于软件的Joel》,他说了一种有关特定类型的程序员的一些知识,他们知道Java / C(面向对象编程语言)中的int和Integer之间的区别。

那么区别是什么呢?

解决方案:

在Java中," int"类型是原始类型,而" Integer"类型是对象。

在C#中," int"类型与" System.Int32"相同,并且是一个值类型(即更像Java的" int")。可以将整数(就像其他任何值类型一样)装箱("包装")到对象中。

对象和基元之间的差异在一定程度上超出了此问题的范围,但可以总结一下:

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

好吧,在Java中,一个int是一个原语,而一个Integer是一个Object。意思是,如果我们创建了一个新的整数:

Integer i = new Integer(6);

我们可以在i上调用一些方法:

String s = i.toString();//sets s the string representation of i

而使用int的情况:

int i = 6;

我们不能在其上调用任何方法,因为它只是一个原始类型。所以:

String s = i.toString();//will not work!!!

会产生错误,因为int不是对象。

int是Java中少数几个原语之一(以及char和其他一些原语)。我不确定100%,但是我认为Integer对象或者多或者少只是具有一个int属性和一整套与该属性进行交互的方法(例如,例如toString()方法)。因此,Integer是使用int的一种理想方式(就像String可能是使用一组char的一种理想方式)一样。

我知道Java不是C,但是由于我从未使用C编程,因此这是我能找到的最接近的答案。希望这可以帮助!

整数对象javadoc

整数对象与整数基本类型的比较

在C#中,int只是System.Int32的别名,System.String的字符串,System.Double的double等等。

我个人更喜欢int,string,double等,因为它们不需要using System;声明:)一个愚蠢的原因,我知道...

我将添加到上面给出的出色答案中,并讨论装箱和拆箱,以及如何将其应用于Java(尽管也请使用Chas)。我将仅使用Java术语,因为我对此更为满意。

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

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版本简短,但是两个版本都生成相同的字节码。因此,尽管自动装箱和自动拆箱非常方便,因为我们只需编写较少的代码,但是这些操作确实在幕后发生,并且运行时成本相同,因此我们仍然必须意识到它们的存在。

希望这可以帮助!

我将在此处发布,因为其他一些帖子相对于C#来说有些不准确。

正确:int是System.Int32的别名。
错误:float不是System.Float的别名,而是System.Single的别名

基本上,int是C编程语言中的保留关键字,并且是System.Int32值类型的别名。

float和Float是不一样的,因为" float"的正确系统类型是System.Single。像这样的某些类型具有保留的关键字,这些关键字似乎与类型名称不直接匹配。

在C中,除了定义枚举时," int"和" System.Int32"或者任何其他对或者关键字/系统类型之间没有区别。使用枚举,我们可以指定要使用的存储大小,在这种情况下,我们只能使用reserved关键字,而不能使用系统运行时类型名称。

是否将int中的值存储在堆栈中,内存中还是作为引用的堆对象取决于上下文以及如何使用它。

此声明中的一种方法:

int i;

定义类型为System.Int32的变量i,该变量位于寄存器中或者位于堆栈中,具体取决于优化。类型(结构或者类)中的同一声明定义一个成员字段。方法参数列表中的相同声明定义了一个参数,具有与局部变量相同的存储选项。 (请注意,如果我们开始将迭代器方法引入组合中,则本段无效,因为它们完全是不同的野兽)

要获取堆对象,可以使用装箱:

object o = i;

这将在堆上创建i内容的盒装副本。在IL中,我们可以直接访问堆对象上的方法,但是在C中,我们需要将其强制转换回int,这将创建另一个副本。因此,如果不创建新int值的新框式副本,就无法在C中轻松更改堆上的对象。 (糟糕,本段内容并不太容易理解。)

对于Java,这已经得到了答案,这是Canswer:

在Cand中," Integer"不是有效的类型名称。" 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 1.5和自动装箱,比较Integer对象时有一个重要的"怪癖"起作用。

在Java中,值-128到127的Integer对象是不可变的(也就是说,对于一个特定的整数值(例如23),通过程序实例化的所有Integer对象(值23)都指向完全相同的对象)。

示例,返回true:

Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2); //  true

虽然返回false:

Integer i1 = new Integer(128);
Integer i2 = new Integer(128);
System.out.println(i1 == i2); //  false

==通过引用进行比较(变量是否指向同一对象)。

根据我们所使用的JVM,此结果可能会有所不同,也可能不会有所不同。 Java 1.5的规范自动装箱要求整数(-128到127)始终装箱到同一包装对象。

一个解法? =)比较Integer对象时,应始终使用Integer.equals()方法。

System.out.println(i1.equals(i2)); //  true

java.net上的更多信息bexhuff.com上的示例

在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);

变量2作为参考传递给持有整数2的对象。

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

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

调用增量时,它将引用(指针)传递给变量a。增量函数直接修改变量a。

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

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

我们现在看到区别了吗?

我在以前的答案中没有看到的另一件事:
在Java中,原始包装器类(例如Integer,Double,Float,Boolean ...和String)被假定为不变的,因此,当我们传递这些类的实例时,被调用的方法无法以任何方式改变数据。与大多数其他类一样,可以通过其公共方法来更改内部数据。因此,除了构造函数之外,此类仅具有" getter"方法,而没有" setter"方法。

在Java程序中,字符串文字存储在堆内存的单独部分中,仅是文字的一个实例,以节省重用这些实例的内存

在Java之类的平台中," int"是基元,而" Integer"是一个持有整数字段的对象。重要的区别是,基元总是按值传递,而按定义是不可变的。

任何涉及原始变量的操作都始终返回新值。另一方面,对象通过引用传递。可能有人争辩说,指向对象的点(也称为引用)也正在通过值传递,但内容并未传递。