java int类型_Java里把int基本类型变成Integer包装类,有啥用?

这是Java(或者很多OO语言)面临的共同设计问题。OO语言都希望能“万物皆对象”,并以此为基础来设计整个语言。比如会提供基类Object,以及基于这个基类的类型系统;

有了Object,就能统一对内存的管理——在托管堆上管理,并且实现GC;

可以支持多态的方法调用。比如写foo.doSomething()这样的代码时,是要去根据foo的类型去查找真正要调用的doSomethinig到底是哪个;顺着这个思路,可以在基类Object中塞一些非常基础的方法(toString、equals等),并让上层可以“直接复用”或者“覆写“;

一切看上去很美好。

但现实中的大量代码不需要像对象那样在托管堆上分配内存,不需要GC,不需要“方法”。他们仅仅需要在栈上快速的分配空间,利用最基本的运算符进行运算、比较和赋值。【对象】对于这类代码显得非常多余且低效。想象下要对一堆整数进行排序,直接分配一段内存,再用快排这类算法直接“过一边“内存上的值就可以了。这远比整出一堆【对象】再通过其引用折腾来折腾去,再GC掉好得多。如果你做过高性能计算之类的程序,相信你明白我在说啥。

这就引入了一个两难的问题,一方面期望用“万物皆对象”的方式来统一语言设计,但另一方面又不得不考虑对“值类型”数据提供支持。

对于这个问题,一般都采用boxing/unboxing的方式实现。即对于每一种数据类型(primitive type),提供一个对应的引用类型(reference type)。把值类型转换成引用类型对象,相当于创建一个“Wraper”对象,被称为装箱(boxing)。反过来,把一个引用类型里的值取出来,被称为拆箱 (unboxing)。

Integer a = new Integer(1); // 装箱int b = a.intValue(); // 拆箱

人肉boxing/unboxing是反直觉的。本来程序员考虑1、true,2.35这样的值就可以了,但就因为其内存模型不一样,不得不考虑到底要用值还是要用对象。而且最郁闷的是,程序员经常一会只想用值,一会想用对象(比如想调用个方法)。

Java 1.4之前,boxing/unboxing是必须手工做的。也就是程序员必须手写上面的代码,不胜其烦。

Java 1.5终于提供了“auto” boxing/unboxing,即让编译器自动帮助插入boxing/unboxing代码。这样就可以像下面这样写代码了。

Character c = 'c'; // 'c'这个值被自动装箱,并把变量c赋值为装箱后的对象的引用。List list = new ArrayList();

list.add(1); // 1 这个值被自动装箱,并把装箱好的对象引用塞给listint v = list.get(0); // list里的第0个对象被取出,自动拆箱,把值赋给v

这的确避免了很多繁琐的boxing/unboxing代码。

但到目前为止Java里始终不能这么做:

1.toString(); // Java里编译错误

这个代码在C#和javascript里都是合法的。原理很简单,只要把1直接装箱成一个对象,然后在上面调用方法就行了。基于JVM的kotlin和groovy也都支持这么干。但Java偏偏懒得搞。

Java的另外一个问题是始终无法对primitive type做真正的collection。Java里提供的collection里只能存引用类型。这会让一些场景很不方便。不想boxinig/unboxing,一个值就弄出一个对象即可,代价有点,但也不高。但对于collection,每次整体复制一遍代价就太高了。因此primitive type必须有自己的collection。Java只有数组可以这样做,但数组的大小不可变,使用起来并不方便。同时Java也没有其他set,map之类的primitive collection。

C#早期和Java一样,但随后提供了“真范型“并重新提供了一套新的Collection,彻底解决了这个问题。这点要赞一下。顺便提一句C#提供了值类型struct,可以让程序员直接管理数据的内存布局,甚至还可以“pin”住一个对象在内存中的位置,避免其因为GC导致内存位置变化。这些Java都没有提供。因此Java始终也无法满足系统编程领域的需求。

最好的auto boxing/unboxing就是让程序员感受不到它们的存在,并自动产生最有效率,最低代价的代码。

如果简单回答题主的问题,把int编程Integer,就可以用Integer的方法,用Java built-in的collections等。但是深究一下,其实Java是可以做得更好一些,让语言更能符合直觉。但我也清楚Java大概率不可能做这种修改的。只能捏着鼻子用了。

扩展下,boxing/unboxing本质上是由于“万物皆对象”落地时带来的一个有点恶,但不得不面对和解决的问题。但如果,不再要求“万物皆对象”,是否可以呢?

以 1.toString(); 这个代码为例子。假如不从OO角度出发,仅仅是作为一种函数的语法糖。当编译器碰到这段代码,就直接去找一个

toString(int self);

的函数是否可以呢?进一步的,提供:

toString(char self);

toString(boolean self);

toString(float self);

……

满足全部built-in的值类型的需要,是否可以呢?

大家可以思考下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值