IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 判断数字字符——Character.isDigit(char ch)实现源码详解 -> 正文阅读

[Java知识库]判断数字字符——Character.isDigit(char ch)实现源码详解

目录


函数的使用

??? 使用场景

举例:返回字符串s中的所有数字之和。易知s中的数字分别为{3,2,3,5,3,5,2,0},其和为23
s = " f3@$23%5Q3Zh52=0"
源码如下:
    private static int NumbSum(String s){
        int sum = 0;
        char [] data = s.toCharArray();
        for(int i = 0;i < data.length;i++){
            if(Character.isDigit(data[i])){
                sum += data[i] - '0';//将char数字转换为int
            }
        }
        return sum;
    }

??? 实现结果

在这里插入图片描述


源码解析

挨个判断已转化为字符数组中的数据是否为数字是解题的关键,即必须理解的Character.isDigit(data[i])的实现过程。在解析源码之前需要掌握字符与数字之间的对应关系,在ASCII编码中,字符与数字的对应关系如下表所示:

在这里插入图片描述

??? Character.isDigit(char ch)源码解析

在Java.lang包中Character类中找到isDigit(char ch)方法。isDigit(char ch)方法根据ascii码表将字符类型ch转换为int类型并传给Character类中的isDigit,通过查阅ascii码表知道 ‘0’-‘9’字符对应整数区间为48~57.
    /**
     * General category "Nd" in the Unicode specification.
     * @since   1.1
     */
	public static final byte DECIMAL_DIGIT_NUMBER        = 9;
	
  	public static boolean isDigit(char ch) {
        return isDigit((int)ch);
    }


    public static boolean isDigit(int codePoint) {
        return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
    }

通过源码可以分析出,函数的实现过程为:首先将传入的字符转换为对应的ASCII码值,然后将ASCII码值传入getType方法,看是否返回的值为9,若为9,则标识传入的字符为数字字符,否则反之。那么。getType方法到底如何实现判断字符类型,为什么返回的值要与9进行对比呢?

??? Character.getType(int codePoint)源码解析

    public static int getType(int codePoint) {
        return CharacterData.of(codePoint).getType(codePoint);//注:此getType方法为CharacterData.of返回实例的getType方法。
    }

getType方法调用了同在java.lang包中CharacterData的静态方法of(int ch)。

    static final CharacterData of(int ch) {
        if (ch >>> 8 == 0) {     // fast-path
            return CharacterDataLatin1.instance;
        }else{
        		……
      	}

of方法返回了CharacterData的子类CharacterDataLatin1的实例

static final CharacterDataLatin1 instance = new CharacterDataLatin1();

通过源码可以分析出,Character.getType(int codePoint)方法的实现结果为,返回一个CharacterDataLatin1的实例,然后调用CharacterDataLatin1的getType方法。返回CharacterDataLatin1实例instance时,会自动执行CharacterDataLatin1类中的静态代码块中的代码给int类型数组A赋值。

	static final int A[] = new int[256];
	
    static {
                { // THIS CODE WAS AUTOMATICALLY CREATED BY GenerateCharacter:
            char[] data = A_DATA.toCharArray();
            assert (data.length == (256 * 2));
            int i = 0, j = 0;
            while (i < (256 * 2)) {
                int entry = data[i++] << 16;
                A[j++] = entry | data[i++];
            }
        }

    }  

其中,A_DATA为类中定义的字符串(注:下面不是乱码为512个16进制表示的数)。静态代码将A_DATA字符串转换为字符数组,然后通过循环,将相邻两个4个字节表示的数字拼接为8个字节表示的数并存储在数组A中。

static final String A_DATA =
“\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800”+
“\u100F\u4800\u100F\u4800\u100F\u5800\u400F\u5000\u400F\u5800\u400F\u6000\u400F”+
“\u5000\u400F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800”+
“\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F”+
“\u4800\u100F\u4800\u100F\u5000\u400F\u5000\u400F\u5000\u400F\u5800\u400F\u6000”+
“\u400C\u6800\030\u6800\030\u2800\030\u2800\u601A\u2800\030\u6800\030\u6800”+
“\030\uE800\025\uE800\026\u6800\030\u2000\031\u3800\030\u2000\024\u3800\030”+
“\u3800\030\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800”+
“\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u3800\030\u6800\030”+
“\uE800\031\u6800\031\uE800\031\u6800\030\u6800\030\202\u7FE1\202\u7FE1\202”+
“\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1”+
“\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202”+
“\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1\202\u7FE1”+
“\202\u7FE1\uE800\025\u6800\030\uE800\026\u6800\033\u6800\u5017\u6800\033\201”+
“\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2”+
“\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201”+
“\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2\201\u7FE2”+
“\201\u7FE2\201\u7FE2\201\u7FE2\uE800\025\u6800\031\uE800\026\u6800\031\u4800”+
“\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u5000\u100F”+
“\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800”+
“\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F”+
“\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800”+
“\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F\u4800\u100F”+
“\u3800\014\u6800\030\u2800\u601A\u2800\u601A\u2800\u601A\u2800\u601A\u6800”+
“\034\u6800\030\u6800\033\u6800\034\000\u7005\uE800\035\u6800\031\u4800\u1010”+
“\u6800\034\u6800\033\u2800\034\u2800\031\u1800\u060B\u1800\u060B\u6800\033”+
“\u07FD\u7002\u6800\030\u6800\030\u6800\033\u1800\u050B\000\u7005\uE800\036”+
“\u6800\u080B\u6800\u080B\u6800\u080B\u6800\030\202\u7001\202\u7001\202\u7001”+
“\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202”+
“\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001”+
“\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\u6800\031\202\u7001\202”+
“\u7001\202\u7001\202\u7001\202\u7001\202\u7001\202\u7001\u07FD\u7002\201\u7002”+
“\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201”+
“\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002”+
“\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\u6800”+
“\031\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002\201\u7002”+
“\u061D\u7002”;

??? CharacterDataLatin1.getType(int codePoint)源码解析

    int getType(int ch) {
        int props = getProperties(ch);
        return (props & 0x1F);
    }

    int getProperties(int ch) {
        char offset = (char)ch;
        int props = A[offset];
        return props;
    }

根据ACCII编码规则,‘0’-‘9’数字字符对应整数为48-57,将其作为数组偏移量,对应A_DATA字符串的

\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800”+
“\u3609\u1800\u3609\u1800\u3609\u1800\u3609\u1800\u3609

其对应A数组中的值为
A[48]:18003609
A[49]:18003609
………………
因此,若ch为数字字符,则getProperties(ch)会返回props = 0x18003609,则

props & ox1F = 9

总结

判断字符是否为数字字符,是根据其ASCII码值在CharacterDataLatin1()中返回值是否为9实现的。CharacterDataLatin1()中存在数组A,以数字字符对应ACII码为数组偏移量返回的值最后两个字节与0x1F结果为9.
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:33:33  更:2022-05-01 15:35:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:02:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码