java基本数据类型的声明_Java基本数据类型和包装类的声明、编译和初始化(转)...

注:本文作者是阿里巴巴B2B的曹龙强;

引言

在平时的开发中,声明一个数字类型的变量,一般有以下几种形式:

1

int

a = 1;

2

Integer b =

1;

3

Integer c =

new Integer(1);

4

Integer d =

Integer.valueOf(1);

int类型为基本数据类型,a指向的是一个字面量,不是类的对象实例,它是编译期可知的。b、c、d一样,都是指向的类对象实例的引用。

字节码分析

上面这段代码编译后的class文件,用javap命令解析后,可以看到字节码指令如下:

1

Code:

2

Stack=3,

Locals=5, Args_size=1

3

//将int型值1推至栈顶

4

0: iconst_1

5

//将栈顶的int型值放入本地变量表中的第二个

6

1: istore_1

7

//将int型值1推至栈顶

8

2: iconst_1

9

//调用java.lang.Integer的静态方法valueOf(java.lang.Integer),参数是栈顶的元素,并将返回值放入栈顶

10

3: invokestatic #16;

//Method

java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

11

//将栈顶的引用类型值放入本地变量表中的第三个

12

6: astore_2

13

//创建一个Integer对象

14

7: new

#17;

//class java/lang/Integer

15

//将该对象的引用压入栈顶

16

10: dup

17

//将int型值1推至栈顶

18

11: iconst_1

19

//调用java.lang.Integer类的初始化方法,该方法参数是栈顶的int型元素,返回值放入栈顶

20

12: invokespecial #22;

//Method

java/lang/Integer."":(I)V

21

//将栈顶的引用类型值放入本地变量表中的第四个

22

15: astore_3

23

//将int型数值1压制栈顶

24

16: iconst_1

25

//调用java.lang.Integer的静态方法valueOf(java.lang.Integer),参数是栈顶的元素,并将返回值放入栈顶

26

17: invokestatic #16;

//Method

java/lang/Integer.valueOf:(I)Ljava/lang/Integer;

27

//将栈顶的引用类型值放入本地变量表中的第四个

28

20: astore 4

29

22: return

通过分析上面的java字节码,可以印证开始的b/c/d都是指向Integer类的对象实例的论证。

但是又有了下面的问题:

1

System.out.println(a

== b);

2

System.out.println(a

== c);

3

System.out.println(a

== d);

4

System.out.println(b

== c);

5

System.out.println(b

== d);

6

System.out.println(c

== d);

输出是:

1

true

2

true

3

true

4

false

5

true

6

false

可见,a与bcd都相等而bc、cd不相等,bd相等,这是为什么呢?

首先,a与bcd都相等,这是常识了。当和包装类对比的对象是其对应的基本类型时,包装类会自动拆箱成基本数据类型与之对比。而bcd都是对象,相互对比的话,自然就是对比的引用地址了,由此,因为c是new

Integer的操作,所以bc、cd不相等也是很显而易见的,那为什么bd是相等的呢?

源码分析

我们可以在编译后的字节码的分析中看到,b和d的初始化过程是一样的,都是调用了Integer的valueOf静态方法,难道这个方法里有乾坤?

1

public

static Integer valueOf(int i) {

2

if(i

>= -128

&& i

<= IntegerCache.high)

3

return

IntegerCache.cache[i + 128];

4

else

5

return

new Integer(i);

6

}

上面是Integer类valueOf方法的源码。

代码中,首先根据参数值和IntegerCache.high值和-128做了对比,如果参数值在此范围内的话,则返回IntegerCache中的一个数组元素,否则,则返回一个新的Integer对象。

那如此看来,b和d初始化时,返回的都是IntegerCache的同一个数组元素值了?

再去看看IntegerCache。

1

private

static class IntegerCache

{

2

static

final int high;

3

static

final Integer cache[];

4

static

{

5

final

int low

= -128;

6

// high value may

be configured by property

7

int

h = 127;

8

if

(integerCacheHighPropValue !=

null)

{

9

// Use Long.decode

here to avoid invoking methods that

10

// require

Integer's autoboxing cache to be initialized

11

int

i =

Long.decode(integerCacheHighPropValue).intValue();

12

i = Math.max(i,

127);

13

// Maximum array

size is Integer.MAX_VALUE

14

h = Math.min(i,

Integer.MAX_VALUE - -low);

15

}

16

high = h;

17

cache =

new Integer[(high - low) + 1];

18

int

j = low;

19

for(int

k = 0; k <

cache.length; k++)

20

cache[k] =

new Integer(j++);

21

}

22

private

IntegerCache() {}

23

}

IntegerCache

是Integer类的私有静态内部类,有两个静态元素,int型的high和Integer数组cache[].分析源码可以看到,该类主要是在初始化的时候初始化cache[]数组,其大小是high-low+1,默认情况下,大小是256,元素数值范围是[-128,127],这不也是byte类型的数值范围么?如果在JVM启动的时候设置了java.lang.Integer.IntegerCache.high参数,则cache的大小及数值由integerCacheHighPropValue决定。

由此说明,b和d返回同一个实例论证成功,那么对于如下程序呢?

1

Integer e =

200;

2

Integer f =

200;

3

System.out.println(e

== f);

这个是打印true还是false呢?不用说了吧~~

练习一下

下面例子的打印呢?

1

Integer a =

1;

2

Integer b =

2;

3

Integer c =

3;

4

Integer d =

3;

5

Integer e =

321;

6

Integer f =

321;

7

Long g =

3L;

8

9

System.out.println(c

== d);

10

System.out.println(e

== f);

11

System.out.println(c

== (a+b));

12

System.out.println(c.equals(a+b));

13

System.out.println(g

== (a+b));

14

System.out.println(g.equals(a+b));

结果:

true

false

true

true

true

false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值