java数据类型 自动拆_java的数据类型、自动拆装箱、字面量

public classTest {public static voidmain(String args[]) {

Integer a= 1;

Integer b= new Integer(1);

Integer c= inc(0);

}public static intinc(Integer x) {return x + 1;

}

}

所谓自动拆箱,就是反过来,在需要使用值的地方,允许你传一个对象,比如:

public classTest {public static voidmain(String args[]) {int a = new Integer(1);int b = Integer.valueOf(1);int c = inc(0);

}public staticInteger inc(Integer x) {return x + 1;

}

}

public classTest {public static voidmain(String args[]) {

Integer a= new Integer(1);

Integer b= Integer.valueOf(1);

Integer c= inc(0);

Integer d= 1;

System.out.println(a== b); //false

System.out.println(a.equals(b)); //true

System.out.println(a== c); //false

System.out.println(a.equals(c)); //true

System.out.println(a== d); //false

System.out.println(a.equals(d)); //true

System.out.println(b== c); //true

System.out.println(b.equals(c)); //true

System.out.println(b== d); //true

System.out.println(b.equals(d)); //true

System.out.println(((Long)1L) == 1); //true

System.out.println(new Long(1).equals(1)); //false

Long e= 100;

Long f= 100;

System.out.println(e== f); //true

e = 1000;

f= 1000;

System.out.println(e== f); //false

}public staticInteger inc(Integer x) {return x + 1;

}

}

wrapper类留下了多少坑,由此可见一斑,这也许还不是全部的,因为我的例子构造的未必那么全。这已经不是一个设计的品味或者取舍权衡的问题了。这完全就是错误的。为了使这种错误少出现,我们能不使用外包类的时候还是尽量不要使用外包类,除非在使用容器,泛型等等的时候,不得不使用。跟这么多出乎意料的结果比起来,审美和品位已经不是最重要的了。

我们还是尝试着解答一下上面的各个结果。首先明确一点,"=="判断的是两边的对象是不是同一个对象,即两个引用指向同一个对象。"equals"是函数,如何实现取决于类里如何定义。我们以JDK中Long的源代码举例:

classLong {public Long(longvalue) {this.value =value;

}private static classLongCache {privateLongCache(){}static final Long cache[] = new Long[-(-128) + 127 + 1];static{for(int i = 0; i < cache.length; i++)

cache[i]= new Long(i - 128);

}

}public static Long valueOf(longl) {final int offset = 128;if (l >= -128 && l <= 127) { //will cache

return LongCache.cache[(int)l +offset];

}return newLong(l);

}//神坑!!!!

public booleanequals(Object obj) {if (obj instanceofLong) {return value ==((Long)obj).longValue();

}return false;

}

}

可以看到,直接使用new构造一个长整型的时候,会生成一个新的对象。而使用 valueOf 的时候,如果参数位于[-128, 127]这个区间内,则直接从cache数组中取一个对象,而不是新建,这就回答了为什么e 和 f 为100时,"=="为true,而 e 和 f 为1000时, "=="为false。

自动装箱时,Java调用了valueOf函数,拆箱时,调用 xxxValue 函数。这就回答了,为什么b, c, d 是同一个对象,而与a却是不同的对象。

比较难理解的是

System.out.println(((Long)1L) == 1); //true

System.out.println(new Long(1).equals(1)); //false

“==”操作符的左边是一个Long型的对象,为了比较就使用了自动拆箱,左边拆箱成了整数1,所以与右边的值是相等的。而第二行,equals参数接受一个Object对象,所以1就被自动装箱成了Integer.valueOf(1),我们看一下Long的equals的实现。如果传进来的是Long型的,那么就比较值,如果传进来的是其他类型,直接返回false。。。。我隔着屏幕似乎都听到了你说“我擦嘞"的声音。。。

字面量:

字面量(literal)是用于表达源代码中一个固定值的记号。

定义看上去不那么直观。其实很简单,整数1,2, 3是整型字面量;用引号引起来的"hello world",是字符串(String)字面量;1.0, 2.1是浮点型字面量;'a', 'c'是字符型字面量。可以使用字面量初始化primitive类型,也可以用于初始化某些特定的对象。例如:

public classTest {public static voidmain(String args[]) {int a = 1;char c = 'z';

String s= "hello java!";double[] t = {1.0, 2.1, 3.4};

}

}

Java允许通过字面量给String类型的对象赋值,却不允许字面量本身就是一个对象。对于一个强对象的语言,这其实是很落后的做法。我们来看几个其他语言的例子:

#Python,字符串连接的写法

"-".join["hello", "world"] #hello-world

//javascript

var d = {"hello" : 1, "world" : 2};

其实JSON的结构不过就是javascript的字典类型的字面量而已。这种数据即代码的做法才是现代语言应该具备的特征。

我们看到,在很多种语言中,都可以把字面量当做一个对象进行调用。例如groovy和ruby里,都可以直接在一个整数上调用times,代表后面的代码块要执行多少次。在这些语言里,才真正的一切都是对象,就连函数都是对象(这个扯远了,我们会尝试在课程里引入一些scala的知识,会介绍函数做为对象带来了哪些变化)。

对比起来,Java不仅字面量不是对象,而且字面量向对象的转变还留下了一个个不大不小的坑。这已经不是bad taste的问题,而是强对象这件事情,Java 根本就没做对。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值