`
gao_20022002
  • 浏览: 164833 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

源码解读

阅读更多

 

 


转载:

 

先找了一个最简单的java.lang.Boolean开始解剖。

首先我们剔除所有的方法和静态变量,Boolean的核心代码如下:

public final class Boolean implements java.io.Serializable,Comparable
{
    private final boolean value;
}

很明显,凡是成员变量都是final类型的,一定是immutable class,这个Boolean和String一样,一旦构造函数执行完毕,实例的状态就不能再改变了。

Boolean的构造函数有两个:

public Boolean(boolean value) {
    this.value = value;
}
public Boolean(String s) {
    this(toBoolean(s));
}

都很简单就不多说了。

另外注意到Boolean类实际上只有两种不同状态的实例:一个包装true,一个包装false,Boolean又是immutable class,所以在内存中相同状态的Boolean实例完全可以共享,不必用new创建很多实例。因此Boolean class还提供两个静态变量:

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);

这两个变量在Class Loader装载时就被实例化,并且申明为final,不能再指向其他实例。

提供这两个静态变量是为了让开发者直接使用这两个变量而不是每次都new一个Boolean,这样既节省内存又避免了创建一个新实例的时间开销。

因此,用
    Boolean b = Boolean.TRUE;

    Boolean b = new Boolean(true);
要好得多。

如果遇到下面的情况:
    Boolean b = new Boolean(var);
一定要根据一个boolean变量来创建Boolean实例怎么办?

推荐你使用Boolean提供的静态工厂方法:
    Boolean b = Boolean.valueOf(var);
这样就可以避免创建新的实例,不信看看valueOf()静态方法:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

这个静态工厂方法返回的仍然是两个静态变量TRUE和FALSE之一,而不是new一个Boolean出来。虽然Boolean非常简单,占用的 内存也很少,但是一个复杂的类用new创建实例的开销可能非常大,而且,使用工厂方法可以方便的实现缓存实例,这对客户端是透明的。所以,能用工厂方法就 不要用 new。

和Boolean只有两种状态不同,Integer也是immutable class,但是状态上亿种,不可能用静态实例缓存所有状态。不过,SUN的工程师还是作了一点优化,Integer类缓存了-128到127这256个 状态的Integer,如果使用Integer.valueOf(int i),传入的int范围正好在此内,就返回静态实例。

hashCode()方法很奇怪,两种Boolean的hash code分别是1231和1237。估计写Boolean.java的人对这两个数字有特别偏好:

public int hashCode() {
    return value ? 1231 : 1237;
}

equals()方法也很简单,只有Boolean类型的Object并且value相等才返true:

public boolean equals(Object obj) {
    if (obj instanceof Boolean) {
        return value == ((Boolean)obj).booleanValue();
    }
    return false;
}

顺便提一句:很多人写equals()总是在第一行写:
   if (obj==null) return false;
其实完全没有必要,因为如果obj==null,下一行的
    if (obj instanceof Type)
就肯定返回false,因为(null instanceof AnyType) = false。
详细内容请参考《Effective Java》第7条:Obey the general contract when overriding equals。

其他的方法如toString()就更简单了,只要稍微熟悉java的程序员相信都能写出来,我就不多说了。

★ 总结 ★

1.如果一个类只有有限的几种状态,考虑用几个final的静态变量来表示不同状态的实例。
例如编写一个Weekday类,状态只有7个,就不要让用户写new Weekday(1),直接提供Weekday.MONDAY即可。

2.要防止用户使用new生成实例,就取消public构造函数,用户要获得静态实例的引用有两个方法:如果申明public static var就可以直接访问,比如Boolean.TRUE,
第二个方法是通过静态工厂方法:Boolean.valueOf(?)

3.如果不提供public构造函数,让用户只能通过上面的方法获得静态变量的引用,还可以大大简化equals()方法:
    public boolean equals(Object obj) {
        return this==obj;
    }
可以直接用==比较引用,绝对没有问题,而且效率最高。

4. 为什么JDK的Boolean没有实现上面第3点?因为那两个static变量TRUE和FALSE是在jdk 1.2以后才有的,由于前面的版本已经把构造函数申明为public,所以为了保持客户端代码能够不修改也在后面的版本中运行,只好继续提供public 构造函数。

分享到:
评论

相关推荐

    TMS320F28x源码解读 程序

    《TMS320F28x源码解读——深入理解数字信号处理器的精髓》 在数字信号处理领域,TMS320F28x系列芯片因其高性能、低功耗的特点,被广泛应用于各种复杂系统中,如工业自动化、电力控制、通信设备等。这些系统的核心...

    Netty5.0架构剖析和源码解读.pdf

    Netty5.0架构剖析和源码解读 本文档主要讲述了Netty5.0架构剖析和源码解读,涵盖了Netty的架构、源码分析、NIO入门等方面的知识点。 概述 JAVA 的 IO 演进是一个长期的过程,从传统的 BIO 通信到 NIO 的出现,都...

    HashMap之resize()方法源码解读.docx

    HashMap之resize()方法源码解读 HashMap的resize()方法是HashMap中最核心的方法之一,该方法负责扩容HashMap的容量,以便存储更多的键值对。下面我们将对HashMap的resize()方法进行源码解读,了解其扩容机制和原理...

    Postgresql源码解读.docx

    4500页的源码解读 光是SELECT语句相关实现,就阐述了300多页 看完了你就是postgreSQL达人了 章节明细,需要精读那个功能点就仔细看

    菜鸟 Spring 源码解读 推荐流程

    首先,源码解读对于任何开发者来说都是提升技术能力的重要途径。通过阅读源码,我们可以更直观地了解框架的工作原理,从而更好地利用它。Spring框架的设计理念和实现方式对许多其他Java框架产生了深远影响,因此深入...

    netty5.0架构剖析和源码解读

    Netty5.0架构剖析和源码解读,旨在为读者提供深入理解Netty内部工作机制的途径,通过源码层面的分析帮助开发者更好地掌握Netty的应用和优化。 1. JAVA的IO演进 在Netty 5.0之前,Java IO主要经历了BIO到NIO的演进...

    jmesa的源码解读(共五部分)

    Jmesa是一个开源的数据分析和展示工具,其源码解读主要涵盖了五个部分,分别是包结构、limit包、core包、core.filter包和view包。在本文中,我们将深入理解Jmesa的核心概念和主要功能。 首先,我们关注的是包结构。...

    QCAD 源码解读

    总的来说,QCAD源码解读是一个深度学习和实践C++、Qt、CAD技术的过程。通过对源码的深入研究,不仅可以提升编程技能,还能更好地理解CAD软件的工作原理,这对于开发定制化的CAD应用或扩展QCAD功能具有极大的价值。

    Spark core 源码解读与扩展

    ### Spark Core 源码解读 Spark Core源码的解读涉及到理解以下几个关键部分: 1. **架构组件**:在Spark的主从架构中,包括Driver和Executor两种角色。Driver负责作业的分解和任务调度,而Executor则执行Driver...

    CesiumJS 2022^ 源码解读[7] - 3DTiles 的请求、加载处理流程解析.doc

    CesiumJS 2022 源码解读 - 3DTiles 的请求、加载处理流程解析 本文将详细介绍 CesiumJS 中 3DTiles 的请求、加载处理流程,并对 3DTiles 的数据集类型、瓦片树的创建、遍历更新、请求并解析瓦片内容等进行详细的...

    Netty5.0架构剖析和源码解读.PDF

    在源码解读方面,我们可以关注以下几个关键部分: 1. **BossGroup 和 WorkerGroup 的实现**:通常基于NIO的Selector实现,BossGroup负责监听新连接,而WorkerGroup处理已连接的SocketChannel。 2. **Channel 实现*...

    Netty5.0架构剖析和源码解读

    通过阅读《Netty5.0架构剖析和源码解读》这本书,你可以深入了解 Netty 的设计哲学,学习如何利用其强大的功能来构建高并发、低延迟的网络应用。同时,这本书也会帮助你更好地理解和运用 Java NIO 技术,提升你的...

    高清Netty5.0架构剖析和源码解读

    Netty5.0 架构剖析和源码解读 作者:李林锋 版权所有 email neu_lilinfeng@ © Netty5.0 架构剖析和源码解读1 1. 概述2 1.1. JAVA 的IO演进2 1.1.1. 传统BIO通信的弊端2 1.1.2. Linux 的网络IO模型简介4 1.1.3. IO...

    jQuery源码解读

    在源码解读中,我们可以看到jQuery的设计思路和实现机制。 首先,jQuery的核心设计是基于JavaScript的闭包特性,以避免命名冲突。整个jQuery库被包裹在一个立即执行的匿名函数中,这样可以确保其中定义的所有函数和...

    源码解读:参照管理系统的功能实现.pptx

    源码解读是软件开发中的一项重要技能,它涉及到对程序源代码的深入理解和分析,以揭示系统的功能实现和设计思路。在《源码解读的基本原理》中,我们了解到源码解读能够帮助我们理解系统的运作机制,提升编程能力,并...

    Resin源码解读1

    《Resin源码解读》 Resin,作为一个高性能的Java应用服务器,其源码解析对于我们深入理解Web服务器的运行机制和优化技术具有重要的价值。本文将从日志分析、运行时调试、网络模型以及线程池模型四个方面进行深入...

    Spark-2.3.1源码解读

    Spark-2.3.1源码解读。 Spark Core源码阅读 Spark Context 阅读要点 Spark的缓存,变量,shuffle数据等清理及机制 Spark-submit关于参数及部署模式的部分解析 GroupByKey VS ReduceByKey OrderedRDDFunctions...

Global site tag (gtag.js) - Google Analytics