变量

注意事项

  1. Java 是强类型语言,变量在使用前必须指明数据类型
  2. 变量在使用之前必须初始化
  3. 变量不能重复声明

命名

  1. 由数字、字母、下划线以及 $ 等组成,其中数字不能开头
  2. 不能使用 Java 语言的关键字,关键字就是 Java 语言用于表示特殊含义的单词
  3. 区分大小写,长度没有限制但不宜过长
  4. 尽量做到见名知意,支持中文但不推荐使用
  5. 标识符可以给 类 / 变量 / 属性 / 方法 / 包 起名字

基本数据类型

在 Java 语言中数据类型主要分为两大类:

  1. 基本数据类型(记住)
    byte、short、int、long、float、double、boolean、char
  2. 引用数据类型(了解)
    数组、类、接口、枚举、标注

占用字节数

整数 小数 布尔值 字符
byte short int long float double boolean char
1 2 4 8 4 8 4 2

在 C++ 中

  • char 是基础数据类型,8 位,1 字节
  • byte 不是基础数据类型,一般是 typedef unsigned char byte,所以 byte 一般是 unsigned char 类型,8 位,1 字节
  • 不同的是,char 的范围是 -128 ~ 127,byte 的范围是 0 ~ 255

在 Java 中

  • char 和 byte 都是基础数据类型
  • byte 和 C++ 中的 char 类型一致,8 位,1 字节,-128 ~ 127
  • char 类型,16 位,2 字节,’\u0000’ ~ ‘\uFFFF’
  • 因为 Java 内部都是用 unicode,所以 Java 才支持中文变量名,如:string 名字 = “Domenic”

整数类型

byte:最小值是 -128(-2^7);最大值是 127(2^7-1);

short:最小值是 -32768(-2^15);最大值是 32767(2^15 - 1);

int:最小值是 -2,147,483,648(-2^31);最大值是 2,147,483,647(2^31 - 1);

long:最小值是 -9,223,372,036,854,775,808(-2^63);最大值是 9,223,372,036,854,775,807(2^63 -1);

char:最小值是 ’\u0000’(即为 0);最大值是 ’\uffff’(即为 65,535);

在 Java 中若要描述比 long 类型还大的数据,需要使用 [java.math.BigInteger](#BigInteger 类) 类型,这些大数会以字符串的形式传入

浮点类型

  1. float 类型在内存空间占 4 个字节,单精度浮点数,可表示 7 位有效数字

    范围:-3.403E38 ~ 3.403E38

  2. double 类型在内存空间占 8 个字节,双精度浮点数,可表示 15 位有效数字

    范围:-1.798E308 ~ 1.798E308

  3. Java 中直接写出的小数叫做字面值,默认为 double 类型,若希望为 float 类型,则需要在后面加上 f 或者 F

布尔类型

Java 语言中用于描述真假信息类型有:boolean,数值只有:true 和 false

布尔类型所占内存大小无明确规定,可认为是 1 个字节

字符类型

其中 char 类型在内存空间中占 2 个字节并且没有符号位,可以表示数字

范围:0 ~ 65535

1
2
char c1 = 'a';    System.out.println((int)c1);  // 打印出来数字
char c2 = 97; // 可以直接赋值数字字面值

常见的 ASCII:’0’ - 48;’A’ - 65;’a’ - 97;空格 - 32;换行符 - 10

Java 字符类型采用 Unicode 字符集编码。Unicode 是世界通用的定长字符集,所有的字符都是 16 位

基本数据类型间的转换

Java 语言中基本数据类型之间的转换方式:自动类型转换 和 强制类型转换

1
2
3
4
5
6
7
flowchart LR
B(byte) --> S(short)
S(short) --> I(int)
C(char) --> I(int)
I(int) --> L(long)
L(long) --> F(float)
F(float) --> D(double)

自动类型转换主要是从 小类型到大类型 间的转换:byte/char/short -> int -> long -> float -> double

强制类型转换主要指从 大类型到小类型 间的转换,语法如下:目标类型 变量名 = (目标类型)源类型变量名;

1
2
3
4
short s1 = 128;     // short 16 位
byte b1 = (byte)s1; // byte 8 位 类型强转后变成了 -128
// 原因:128: 0000 0000 1000 0000 => 1000 0000 (截取 8 位)
// 转换为十进制 => 0111 1111 => 1000 0000 => 128 => -128

引用数据类型

引用数据类型


运算符

自增

1
2
3
int ia = 10
int ib = ia++ // 该语句结束后 ib = 10,ia = 11
int ic = ia++ + ++ia // 该语句结束后,ic = 11 + 13 = 25

赋值

1
2
3
4
5
6
7
8
考点:
byte b1 = 10;
b1 = b1 + 2; // 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失 byte + int 相加结果还是 int 类型
// 所以 b1 + 2 的结果是 int 类型,不能直接赋值给 b1,要写为 b1 = (byte)(b1 + 2);
b1 = b1 + (byte)2; // 错误: 不兼容的类型: 从 int 转换到 byte 可能会有损失 byte + byte 相加结果还是 int 类型
// 编译器优化,因为 byte 类型范围小,防止结果溢出
// 所以 b1 + (byte)2 的结果是 int 类型,不能直接赋值给 b1,要写为 b1 = (byte)(b1 + (byte)2);
b1 = (byte)(b1 + 2); // 正确:强制类型转换,将 int 类型转换为 byte
1
b1 += 2;             // 等价于 b1 = (byte)(b1 + 2);  += 不仅简化了写法,还自带了强转

逻辑

所有以关系运算符作为最终运算的表达式结果一定是 boolean 类型

1
2
3
int ia = 2
ia == 2; // 表示判断变量 ia 的数值是否等于 2
2 == ia; // 表示判断 2 是否等于变量 ia 的数值,从结果上来说等价,推荐该方式(可以规避 == 写成 = 的错误)

自动拆装箱

1
2
3
4
5
6
7
8
9
10
// 基本包装类都有自动拆装箱
int i1 = 1;
Integer i2 = new Integer(1);
i1 == i2; // 结果为 true,i2 会自动拆箱
------------------------------------------------------------------------------------------------------------------
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
str1 == str2; // 结果为 true
str1 == str3; // 结果为 false,String 没有自动拆箱

空指针异常

1
2
3
4
int i1 = 1;
Integer i2 = null;
i1 == i2; // 空指针异常,int 和 Integer 比较,i2 会自动拆箱
// 拆箱过程中要给 i2 赋值 int 的默认值 0,但 i2 为空对象,因此报错

不同类型比较

1
2
3
4
5
6
7
Integer i = 1;
Long l = 1;
i == l; // 结果为 true
i.equals(l); // 结果为 false
Objects.equals(i, l); // 结果为 false
// 因为基本包装类中重写的 equals 会先判断是否比较对象为同一类型,不是就直接返回 false
// equals 和 Objects.equals 都会调用对象自己重写的 equals(如果有),因此为 false

移位

  1. << 左移运算符,用于将数据的二进制位向左移动,右边使用 0 补充

    左移 1 位相当于当前整数的数值乘以 2

  2. >> 右移运算符(算数右移),用于将数据的二进制位向右移动,左边使用符号位补充

    右移 1 位相当于当前整数的数值整除 2

  3. >>> 逻辑右移运算符(无符号右移),用于将数据的二进制位向右移动,左边使用 0 补充

位运算符

  1. & 表示按位 运算符,按照二进制位进行与运算,同 1 为 1,同 0 为 0,不同为 0
  2. | 表示按位 运算符,按照二进制位进行或运算,同 1 为 1,同 0 为 0,有 1 则为 1
  3. ~ 表示按位 取反 运算符,按照二进制位进行取反,1 变为 0,0 变为 1
  4. ^ 表示按位 异或 运算符,按照二进制位进行异或运算,相同为 0,不同为 1

优先级

优先级:数值越小,代表优先级越高

结合方向:表达式中各种运算符的优先级
大多数运算符结合方向是 “自左至右”,即:先左后右,也叫 “左结合性”
例:a-b + c,表达式中有 - 和 + 两种运算符,且优先级相同,按先左后右结合方向
先围绕减号结合,执行 a-b 的运算,再围绕加号结合,相当于:(a-b) + c

优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、-- 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 <<、>>、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= 从右向左

使用技巧

以下几种方式,可以让程序的运行速度更快

  1. 奇偶判断

    用 & 运算符代替 %

    1
    2
    3
    4
    5
    if (num & 1) {
    // 奇数
    } else {
    // 偶数
    }
  2. 数值交换

    用 ^= 异或 XOR 运算符来实现数值交换
    XOR 的规则:相同则为 0,不同则为 1,例:1^0 = 1 , 1^1 = 0 , 0^1 = 1 , 0^0 = 0

    1
    2
    3
    4
    5
    int x = 3;  // x = 0011
    int y = 5; // y = 0101
    x ^= y; // x = 0110,记录了 x 与 y 所有不同的位
    y ^= x; // y = 0011,y 更改了不同的位后,y 就变成了 x
    x ^= y; // x = 0101,x 更改了不同的位后,x 就变成了 y
  3. 乘除以 2

    用 << 代替乘,用 >> 代替除

    1
    2
    n = n << 1;  // 二进制左移 1 位
    n = n >> 1; // 二进制右移 1 位
  4. 计算数字的位数

    用 log 代替 for 循环

    1
    digitCount = floor(log10(N)) + 1;