V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Acceml
V2EX  ›  程序员

Java 为什么要有包装类?

  •  
  •   Acceml ·
    Acceml · 2018-09-04 13:50:34 +08:00 · 3288 次点击
    这是一个创建于 2032 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我谈谈我的理解,欢迎指正!

    为什么这么设计

    java 中 new 一个对象,会把这个对象存储在堆里面,所有的类都是 object 的子类,通过 stack 指向堆。 1.java 中的对象很多都是朝生夕死的,所以一直放在堆中不是很高效; 2.Java 是一个面相对象的编程语言,基本类型并不具有对象的性质,为了让基本类型也具有对象的特征,就出现了包装类型(如我们在使用集合类型 Collection 时就一定要使用包装类型而非基本类型),它相当于将基本类型“包装起来”,使得它具有了对象的性质,并且为其添加了属性和方法,丰富了基本类型的操作。

    不同

    1. 声明方式不同:基本类型不使用 new 关键字,而包装类型需要使用 new 关键字来在堆中分配存储空间;

    2. 存储方式及位置不同:基本类型是直接将变量值存储在栈中,而包装类型是将对象放在堆中,然后通过引用来使用;

    3. 初始值不同:基本类型的初始值如 int 为 0,boolean 为 false,而包装类型的初始值为 null ;

    4. 使用方式不同:基本类型直接赋值直接使用就好,而包装类型在集合如 Collection、Map 时会使用到。

    取舍

    这样做也不是没有代价,装箱和拆箱的性能差距,在大数据和大并发的环境中会被体现出来。 以答主所做的广告系统为例,广告系统中大量存在如下类型的数据: 广告 Id: long 广告价格: double app 的 Id : int ...

    由于 java 提供了默认 box unbox 的操作,例如更新某个广告当前的价格就需要数据结构 Map<Long, Double>,这个时候就自动从 long -> Long , double -> Double. 更新操作还不太明显,但是查询广告价格几乎是每一个请求都会有的,这个时候 box, unbox 就会大大的降低性能。 对此,我们团队线上的代码没有使用 java 的原生 jdk 中的 Map、Set、List 等结构,而是使用了 Eclipse Collections。Eclipse Collections 起源于 2004 年在高盛公司内部开发的一个名为 Caramel 的集合框架。这个框架就可以使得 Map<long,Object>这样的结构,不存在 box 和 unbox。 在我们的广告下发引擎中,上线后大概缩短了 5ms 的 latency.我们团队属于比较尝鲜那种,新的技术够比较敢用,现在线上即将升级 jdk10.有兴趣的小伙伴可以参考官网文档: http://www.eclipse.org/collections/cn/index.html

    下面列出官网文档所给的和原生 jdk 比较的数据.

    image.png

    image.png

    image.png


    Leetcode 名企之路

    8 条回复    2018-09-04 22:35:54 +08:00
    jiqing
        1
    jiqing  
       2018-09-04 13:54:07 +08:00 via Android   ❤️ 1
    文章是挺好的,但是末尾的广告就很硬了。
    简而言之就是,基本数据类型不能当成一个对象使用。包装类可以把基本数据类型转换成一个对象。对象能干的包装类都能干。
    Acceml
        2
    Acceml  
    OP
       2018-09-04 13:56:36 +08:00
    @jiqing 我们线上使用的情况这个对 GC 和延时还是有蛮大影响的,换掉之后大概能缩短 5ms。主要原因是系统太大,涉及到的开发人员太多,大家也不注意。
    feverzsj
        3
    feverzsj  
       2018-09-04 14:00:56 +08:00
    因为 java 很啰嗦
    BBCCBB
        4
    BBCCBB  
       2018-09-04 14:09:16 +08:00
    据我所知,还有 fastutil 库也提供支持原生类型的集合, 但这个库太大了, 10 多 M
    lhx2008
        5
    lhx2008  
       2018-09-04 14:13:41 +08:00 via Android
    如果是大量数据,用 stream 等流式操作库更好,可以控制拆装箱。底层是数组
    hhsuan
        6
    hhsuan  
       2018-09-04 14:14:38 +08:00
    我觉得这个问题可以反过来问:java 为什么要支持原生类型?
    lovedebug
        7
    lovedebug  
       2018-09-04 14:16:16 +08:00
    因为 JVM 中一个对象还是很占内存的,需要存储额外的描述信息。所以额外设计基本类型
    Acceml
        8
    Acceml  
    OP
       2018-09-04 22:35:54 +08:00
    @lhx2008 stream 并不能呢控制 box unbox 吧。

    @BBCCBB 这个库不算大。我们已经在线上使用了,千万级收入的系统,目前效果还不错。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1652 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 16:47 · PVG 00:47 · LAX 09:47 · JFK 12:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.