数据类型

概述

数据类型

注意:

  • 在 Java 中,小数默认类型为 double,整数默认类型是 int
  • 基本数据类型的默认值(开发中尽可能为每一个变量赋初值)
    类型默认值
    byte(byte) 0
    short(short) 0
    int0
    long0L
    float0.0f
    double0.0d
    char\u0000
    booleanfalse

基本数据类型

整型

整型

注意:Java 没有任何无符号(unsigned)形式的 int、long、short 或 byte 类型。 不同进制的表示形式:

  • 十六进制数值有一个前缀 0x0X(如0xCAFE)。
  • 八进制有一个前缀 0,例如,010 对应十进制中的 8 。很显然,八进制表示法比较容易混淆,所以建议最好不要使用八进制常数。
  • 从Java 7开始,加上前缀 0b0B 就可以写二进制数。例如, 0b1001 就是 9 。另外,同样是从 Java 7 开始,还可以为数字字面量加下划线,如用(1_000_0000b1111_0100_0010_0100_0000)表示一百万。这些下划线只是为了让人更易读。Java编译器会去除这些下划线。

浮点类型

浮点类型

可以使用十六进制表示浮点数值。例如,0.125=2^(-3)可以表示成0x1.0p-3。在十六进制表示法中,使用p表示指数,而不是e。 注意,底数采用十六进制,指数采用十进制。指数的基数是2,而不是10。 所有浮点数的计算都遵循 IEEE754 规范。表示溢出和出错情况的三个特殊的浮点数值:

  • 正无穷大(Double.POSITIVE_INFINITY)
  • 负无穷大(Double.NEGATIVE_INFINITY)
  • NaN(不是一个数字,Double.NaN)

判断是否是“非数值” if((Double.isNaN(x)) //check whether x is "not a number"

IEEE 754 浮点数值不适用于无法接受舍入误差的金融计算中。例如,命令System.out.println(2.0-1.1) 将打印出 0.8999999999999999,而不是人们想象的 0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确地表示分数 1/3 一样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal 类。

char 类型

char 类型原本用于表示单个字符。不过,现在情况已经有所变化。如今,有些 Unicode 字符可以用一个 char 值描述,另外一些 Unicode 字符则需要两个 char 值。

char 类型的值可以表示为十六进制值,其范围从 \u0000\uFFFF。 除了转义序列 \u 之外,还有一些用于表示特殊字符的转义序列,请参看表3-3。

escape-sequence.png

  • 所有这些转义序列都可以出现在加引号的字符字面量或字符串中。例如,'\u2122'"Hello\n"
  • 转义序列 \u 还可以出现在加引号的字符常量或字符串之外(而其他所有转义序列不可以)。例如:public static void main(String\u0058\u005D args) 是符合语法规则的,因为 \u0058 \u005D 分别表示 [ ]
    • Unicode转义序列会在 解析代码之前 得到处理。例如, "\u0022+\u0022" 并不是一个由引号(U+0022)包围加号构成的字符串。实际上,\u0022 会在解析之前转换为 ",这会得到 ""+"",也就是一个空串。
    • 更隐秘地,一定要当心注释中的 \u。注释 // \u00A0 is a newline 会产生一个语法错误,因为读程序时 \u00A0 会替换为一个换行符。类似地,下面这个注释 // look inside c:\users 也会产生一个语法错误,因为 \u 后面并未跟着4个十六进制数。

boolean类型

整型值布尔值 之间不能相互转换

基本数据类型的转换

自动转换

条件(需要2个同时满足):

  • 转换前的数据类型与转换后的数据类型兼容
  • 转换后的数据类型的表示范围比转换前的大

补充:任何类型的数据都可向 String 类型转换。例:

System.out.println( "1 + 2 = " + 1 + 2 );
System.out.println( "1 + 2 = " + ( 1 + 2 ) );
// 输出
// 1 + 2 = 12
// 1 + 2 = 3

自动类型转换 注:虚线箭头可能有精度的损失

强制转换

// (欲转换的类型) 变量名称
double x = 9.997;
int nx = (int) x; // 变量nx的值为9。强制类型转换通过截断小数部分将浮点值转换为整型。
  • 如果想对浮点数进行舍入运算,以便得到最接近的整数(在很多情况下,这种操作更有用),那就需要使用Math.round方法:

    double x = 9.997;
    int nx = (int) Math.round(x); // 现在,变量 nx 的值为10。当调用 round 的时候,仍然需要使用强制类型转换(int)。其原因是round 方法返回的结果为 long 类型,由于存在信息丢失的可能性,所以只有使用显式的强制类型转换才能够将 long 类型转换成 int 类型。
    

复合数据类型

枚举类型

例: 枚举类型 Size 的声明:

enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };

声明 Size 类型变量:Size s = Size.MEDIUM;

注意:Size 类型的变量只能存储这个类型声明中给定的某个枚举值,或者 null 值。

补充:

跟类定义一样,枚举类型可以单独放在一个文件里,当一个枚举类型用 public 修饰时,它对其他包可见,否则只对同一个包中的类可见,这和类定义是一样的。

标识符 SMALL, MEDIUM 等就称为枚举常量(enumeration constants)

每一个枚举常量被隐式的声明成 Day 的一个 publicstatic 成员,而且其类型为 Size ,亦就是说这些常量是 self-typed

参考:Java 里有枚举类型吗?如何定义?

字符串

  • 字符串是不可变的
  • 使用equals()方法比较字符串内容
    • 如果虚拟机始终将相同的字符串共享,就可以使用 == 运算符检测是否相等。但实际上只有字符串常量是共享的,而 +.substring(parm) 等操作产生的结果并不是共享的。因此,千万不要使用 == 运算符测试字符串的相等性,以免在程序中出现糟糕的 bug。从表面上看,这种 bug 很像随机产生的间歇性错误。
  • 空串:str.length() == 0str.equals("")
  • Null串:str == null

length 方法

  • Java 语言里 String 在内存中以是 UTF-16 方式编码
  • "".length():The length is equal to the number of Unicode code units in the string.
  • 因此,实际length方法在Java中返回的是UTF-16的代码单元数目。
  • BMP内的字符转义\uXXXX即可(Unicode转义序列会在解析代码之前得到处理)
  • 增补平面内的字符转义写成 UTF-16 的代理对形式,例:U+1D11E写作\uD834\uDD1E,虽然是一个字符,但其.length()结果为2
  • 若想得到非BMP的字符数,可以使用codePointCount方法。

getBytes 方法

  • .getBytes() 不过是把「一种编码」的字节数组转换成「另一种编码」的字节数组。
    • 这里的「一种编码」在 Java 中就是 UTF-16。
    • 这里的「另一种编码」则由调用者来指定,不指定就用缺省(JVM的默认编码,JVM启动时如果没有明确指定,则默认使用操作系统的缺省编码)。

运算符

逻辑运算符

名称符号
逻辑非!
逻辑与&
逻辑或|
短路与&&
短路或||
异或^

例:「短路与」示例 (若使用“与”,则会报错(10/0),使用「短路与」则可以正常运行)

public class Demo{
    public static void main(String[] args){
        int n = 10, m = 2;
        boolean k = false;
        if(n != 10 && 10/0 == 9){
            System.out.println(!k);
        }
        else{
            System.out.println(k);
        }
    }
}

位运算符

&     ("and")
|     ("or")
^     ("xor")
~     ("not")
<<    左移
>>    右移(用符号位填充高位)
>>>   (用0填充高位)

运算符优先级

运算符优先级