JavaSE-Adventure(I) : Data Type 数据类型

JavaSE-Adventure (I) : Java Data Type

基本数据类型 (primitive type) & 包装数据类型 (wrapped type)

  • 基本数据类型
    • 整数类型:
      • byte(1 byte), short(2 bytes), int(4 bytes), long(8 bytes)
    • 浮点类型:
      • float(4 bytes), double(8 bytes)
    • 字符类型:
      • char(2 bytes)
    • 布尔类型:
      • boolean(1 byte)
  • 包装数据类型:
    • 整数类型:
      • Byte, Short, Integer, Long
    • 浮点类型:
      • Float, Double
    • 字符类型:
      • Character
    • 布尔类型:
      • Boolean

在这里插入图片描述

自动装箱/拆箱 (auto boxing/unboxing)

Auto Boxing

Integer i = 10;
    L1

    LINENUMBER 8 L1

    ALOAD 0

    BIPUSH 10

    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;

    PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;

根据字节码可以看出, 字面量 10 赋值给 Integer 实际会调用Integer 的静态方法:Integer.valueOf (I);

Auto Unboxing

int n = Integer.valueOf(10); 
    L2

    LINENUMBER 9 L2

    ALOAD 0

    ALOAD 0

    GETFIELD AutoBoxTest.i : Ljava/lang/Integer;

    INVOKEVIRTUAL java/lang/Integer.intValue ()I

    PUTFIELD AutoBoxTest.n : I

从字节码能看出, 拆箱实际是调用了 xx.intValue()

常见问题

  1. 当封装类与基础类型进行 ==、+、-、*、/ 运算时,封装类会进行拆箱,拆箱结果与基础类型对比值;

  2. 而两个封装类进行 == 运算时,与其它的对象的比较一样,对比两个对象的地址,也即判断是否两个引用是否指向同一个对象

范例一:

Integer integer400 = 400;
int int400 = 400;
System.out.println(integer400 == int400); // true	

== 运算, integer400 拆箱, 结果为true

范例二:

Integer integer100 = 100;
int int100 = 100;
System.out.println(integer100.equals(int100)); // true

根据方法参数列表的类型自动选择 装箱or拆箱, 结果为int装箱, true

范例三:

Integer integer100 = null;
int int100 = integer100; // NullPointerException

编译期不会报错

运行时:NullPointerException

问题:int int100 = integer100;

​ integer100 自动拆箱时,null.intValue()

包装数据类型常量池技术

// Integer 常量池源码部分
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true

Integer i1 = 40;	// auto boxing
Integer i2 = new Integer(40); // store heap
System.out.println(i1==i2); // false

缓存 (cache)

整数类型缓存:

Integer:

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Short:

public static Short valueOf(short s) {
    final int offset = 128;
    int sAsInt = s;
    if (sAsInt >= -128 && sAsInt <= 127) { // must cache
        return ShortCache.cache[sAsInt + offset];
    }
    return new Short(s);
}

Byte:

public static Byte valueOf(byte b) {
    final int offset = 128;
    return ByteCache.cache[(int)b + offset];
}

Long:

public static Long valueOf(long l) {
    final int offset = 128;
    if (l >= -128 && l <= 127) { // will cache
        return LongCache.cache[(int)l + offset];
    }
    return new Long(l);
}
Character 缓存:
public static Character valueOf(char c) {
    if (c <= 127) { // must cache
      return CharacterCache.cache[(int)c];
    }
    return new Character(c);
}

扩展:字符、字符集、字符编码

字符(Character)
字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
字符集(Character set)
字符集是一个系统支持的所有抽象字符的集合。通常以二维表的形式存在,二维表的内容和大小是由使用者的语言而定。如ASCII,GBxxx,Unicode等。
字符编码(Character encoding)
字符编码是把字符集中的字符编码为特定的二进制数,以便在计算机中存储。每个字符集中的字符都对应一个唯一的二进制编码。

字符集和字符编码一般都是成对出现的,如ASCII、IOS-8859-1、GB2312、GBK,都是即表示了字符集又表示了对应的字符编码。Unicode比较特殊,有多种字符编码(UTF-8,UTF-16等)

ASCII字符集&编码

ASCII码为单字节,用7位二进制数表示,由于计算机1个字节是8位二进制数,所以最高位为0,即00000000-01111111或0x00-0x7F。

GB2312字符集&编码

GB 2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。

01–09区为特殊符号。
16–55区为一级汉字,按拼音排序。
56–87区为二级汉字,按部首/笔画排序。

举例来说,“啊”字是GB 2312之中的第一个汉字,它的区位码就是1601。
10–15区及88–94区则未有编码。

编码格式:
在使用GB 2312的程序通常采用EUC储存方法,以便兼容于ASCII。

每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。

“高位字节”使用了0xA1–0xF7(把01–87区的区号加上0xA0),“低位字节”使用了0xA1–0xFE(把01–94加上0xA0)。 由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0–0xF7,“低位字节”的范围是0xA1–0xFE,占用的码位是72*94=6768。其中有5个空位是D7FA–D7FE。

GBK字符集&编码

GBK 亦采用双字节表示,总体编码范围为8140-FEFE,首字节在81-FE 之间,尾字节在40-FE 之间,剔除 xx7F一条线。

在这里插入图片描述

GBK向下完全兼容GB2312-80编码。支持GB2312-80编码不支持的部分中文姓,中文繁体,日文假名,还包括希腊字母以及俄语字母等字母。不过这种编码不支持韩国字,也是其在实际使用中与unicode编码相比欠缺的部分。

GB 18030字符集&编码

此标准内的单字节编码部分、双字节编码部分,和四字节编码部分收录的中日韩统一表意文字扩展A区汉字,为强制性标准。其他部分则属于规模性标准。在中华人民共和国境内所有软件产品,都需要支持这个同时包含单字节、双字节和四字节编码的规格。

GB 18030主要有以下特点:

  1. 和UTF-8一样都采用多字节编码,每个字可以由1个、2个或4个字节组成。
  2. 编码空间庞大,最多可定义161万个字元。
  3. 支持中国国内少数民族的文字,不需要动用造字区。
  4. 汉字收录范围包含繁体汉字以及日韩汉字。
    编码方式:
    单字节,其值从0x00到0x7F。
    双字节,第一个字节的值从0x81到0xFE,第二个字节的值从0x40到0xFE(不包括0x7F)。
    四字节,第一个字节的值从0x81到0xFE,第二个字节的值从0x30到0x39,第三个字节从0x81到0xFE,第四个字节从0x30到0x39。

Unicode字符集&编码

UTF-8

UTF-8的特点是对不同范围的字符使用不同长度的编码。

在这里插入图片描述

上表表示如何从一个从Unicode 转化到UTF-8 , 对于前0x7F的字符,UTF-8编码和ASCII码是一一对应的。如果一个字符在000800-00FFFF 之间,那转化到UTF-8 需要用三字节模板,使用16个码位,每个x 就是一个码位。

Java 与 字符: 内码与外码

内码:程序内部使用的字符编码,如java的char,所以java的char是2字节16位;

外码:程序外部交互时使用的字符编码,如class文件。

参考:
字符与编码:https://blog.csdn.net/kuji86/article/details/108783783
Java 与 编码:https://segmentfault.com/a/1190000023345905

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值