原始类型和包装类的主要区别是什么?

7
这两行代码有什么区别?
    int pInt = 500;

并且

    Integer wInt = new Integer(pInt);

或者

    Integer wInt = new Integer(500);
6个回答

18

无。

那完全是一回事。在第一种情况下,你只是有一个附加变量。

请注意,在自动装箱的情况下,您很少需要同时拥有intInteger变量。因此,对于大多数情况而言,这就足够了:

int pInt = 500;

整数类型最有用的情况是区分变量不为已知值(即 null)的情况:

Integer i = null; // possible
int i = null; // not possible because only Object variables can be null

但是不要保留两个变量,一个就足够了。


在包装类中应该有一些不同的方法,例如使用 int p2 = wInt.intValue(); - Bernard
当你可以简单地使用p2=pInt;时,这几乎没有用处。请注意,整数对象甚至不可变。 - Denys Séguret
你说的是区分对象是否为空的好方法。在另一个回答中,@Sumit Singh说我不能定义一个 int 为空,但我可以说 Integer 为空。你怎么看? - Bernard
3
我们的意思是一样的:如果你想要一个未定义的整数,你必须使用一个Integer变量,因为你不能将int变量设置为null。 - Denys Séguret

8
在Java中,原始类型的实例保存实际的值,但是包装类型的实例保存对对象的引用。也就是说,保存了对象可能被找到的位置的地址。
当你编写这样一行程序时:
Integer integer = 500;

编译器将其改为以下内容:
Integer integer = new Integer(500);

这个过程被称为“自动装箱”。 这是将原始实例自动放置在Integer的“盒子”中。 因此,以下程序的输出:
public class PrimitiveToObject {
    public static void main(String[] args) {
        printClassName(1);
        printClassName(1L);
        printClassName((char)1);
    }
    public static void printClassName(Object object){
        System.out.println(object.getClass());
    }
}

这是什么意思:
class java.lang.Integer
class java.lang.Long
class java.lang.Character

同时,还有这个:
int i = integer;

变成了这样:

int i = integer.intValue();

这被称为拆箱
如上所示,变量名为integer的包装器对象使用了点运算符(.),但是i没有使用。也就是说,包装器对象可以取消引用,但是原始实例不行。
封箱和拆箱可能会稍微减慢程序的速度。因此,对于新手来说,包装器可能看起来像是增加的负担,但实际上并非如此。包装器在需要对象成为引用类型的地方使用。例如:Map<Integer,String>map=new HashMap<Integer,String>();是有效的语句,但是Map<int,String>map=new HashMap<int,String>();不是有效的语句。
另一个典型的包装器非常有用的情况是:
在MySQL中,NULLINT类型列的有效条目。但在Java中,int不能有null值,而Integer可以有。这是因为在SQL中NULL表示不可用。因此,如果您正在使用JDBC将整数值插入MySQL表中,那么java程序中的null将有助于在MySQL表中插入NULL
在类似或类比于此的情况下,包装器类也可以非常有用:
Boolean decision; // Using wrapper for boolean.
if("YES".equalsIgnoreCase(consent))
    decision = Boolean.TRUE; // In favour
else if("NO".equalsIgnoreCase(consent))
    decision = Boolean.FALSE; // Not in favour
else if("CAN'T SAY".equalsIgnoreCase(consent))
    decision = null; // Undecided

7

首先

int pInt = 500;,这里的pInt不是一个对象,而在

Integer wInt = new Integer(500); wInt是一个引用

这也是Java不是纯面向对象语言的原因之一。因为在Java中不是所有东西都是对象。


2

包装类将有一个包含原始数据类型的框,这里有8种原始数据类型,分别是byte、int、long、double、float、short、Boolean和char,所有这些都包含在包装类中。

要使用原始数据类型,我们可以像这样使用:int a;

但是要使用包装类,我们需要像这样使用:Integer a = new Integer(i);


1
The types of data are the same, but there are situations where manipulation of objects is more convenient than primitive types, such as data structures, where you need more control of your data types. Objects can be null, while primitive types cannot. Additionally, you cannot call methods in a primitive type (.compareTo(), .equals(), ...) but you can in wrapper classes.
The information below describes the types in primitive and wrapper classes:
Primitive Types | Wrapper Class (Superclass = Object) - boolean - Boolean - char - Character Primitive Types | Wrapper Class (Superclass = Number) - byte - Byte - short - Short - int - Integer - long - Long - float - Float - double - Double To understand how the wrapper classes work, consider the example below:
public final class IntWrapper { 
    private final int intVal;
    IntWrapper(int intVal) {
            this.intVal = intVal;
    }
    public int getInt() {
           return intVal;
   }
}

现在我们可以使用新的IntWrapper类创建一个对象,并将基本类型int值41“装箱”:
int i = 41;
IntWrapper iw = new IntWrapper( i ); // box the primitive int type value into the object
i = iw.getInt(); // unbox the value from the wrapper object

我的示例IntWrapper类是不可变的,不可变意味着一旦其状态被初始化,其状态就无法更改。

当final关键字应用于一个类时,该final类不能被扩展。换句话说,final类永远不能是子类的超类。final类可以是超类的子类,没有问题。当一个类被标记为final时,它的所有方法也隐式地是final的。

需要注意的是,当final应用于引用变量时,它并不防止对象实例的成员更改值。

这个例子是为了更好地理解包装类的工作原理。

接下来,要创建Integer、Double和其他包装类,可以编写:

Integer i = new Integer(4);
Double d = new Double(9.62);
Boolean b = new Boolean("true");
Character c = new Character('M');

为了将封装的数字转换为包装对象,您可以编写以下内容:
long l = i.longValue();
double e = i.doubleValue();
float f = d.floatValue();
short s = d.shortValue();

每个封装类都包括特殊的方法,用于将原始类型转换为表示非数字值的封装对象:
boolean bo = b.booleanValue();
char ch = c.charValue();

在Java 5版本之前,必须使用上述语法从包装类中创建对象,但为了简化这些操作,主要是与Java集合中提供的数据结构相关的值插入(只接受对象)现在存在自动装箱或装箱和自动拆箱或拆箱选项。

自动装箱或装箱允许您将原始值插入到等效包装类型或Object类型的引用中:

// Same result of Double d = new Double(-2.75);
Double objD = -2.75;
// Same result of Object objI = new Integer(13);
Object objI = 13;

自动拆箱或装箱允许您将包装器对象插入到基本类型变量中,自动在等效类型之间转换:
// Same result of double vd = objD.doubleValue();
double vd = objD;
// Same result of int vi = objI.intValue();
int vi = objI;

0

我见过的最重要的实际差异是,Integer 的初始化和计算速度比int慢得多。除非必要,否则我会避免使用Integer

int x = 20_000_000;// 20 millions
for (int i = 0; i < x; i++) {
    ix += 23;
    }

当ix是整数时,完成循环平均需要138毫秒(50次试验的平均值),但当ix是int类型时,只需要10毫秒。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接