JavaSE3️⃣程序基础 - 变量&数据类型&运算

需要了解的计算机基础知识:👉 存储单位 & 数值表示

  1. 存储单位
    1. bit(位):描述电脑数据量的最小单位。
    2. byte(字节):计算机内存的最小存储单位(1byte = 8bit)。
  2. 数值表示:需了解计算机中正负数的表示——符号位(最高位 0 正 1 负)

1、变量

1.1、说明

  1. 类型:分为基本变量、引用变量。
  2. 使用先定义(声明)后使用
    1. 声明时可以赋初始值,声明后可以重新赋值。
    2. 可以赋常量值,也可以赋变量。

1.2、示例分析

针对以下代码,分析 JVM 执行操作。

// 定义变量
int x;
int y = 1;

// 修改变量值
x = 10;
y = x;
  1. int x;

    1. 代码含义:定义变量 x,没有显式赋值(但 int 类型默认值 0);

    2. JVM 操作:分配一个存储单元,变量 x 指向该存储单元。

            x
            │
            ▼
      ┌───┬───┬───┬───┬───┬───┬───┐
      │   │ 0 │   │   │   │   │   │
      └───┴───┴───┴───┴───┴───┴───┘
      
  2. int y = 1;

    1. 代码含义:定义变量 y,赋值 1;

    2. JVM 操作:分配一个存储单元,变量 y 指向该存储单元。

            x       y
            │       │
            ▼       ▼
      ┌───┬───┬───┬───┬───┬───┬───┐
      │   │ 0 │   │ 1 │   │   │   │
      └───┴───┴───┴───┴───┴───┴───┘
      
  3. x = 10;

    1. 代码含义:将变量 x 的值赋为 10;

    2. JVM 操作:找到变量 x 的存储单元,移除原来的值 0,放入新的值10。

             x       y
             │       │
             ▼       ▼
      ┌───┬────┬───┬───┬───┬───┬───┐
      │   │ 10 │   │ 1 │   │   │   │
      └───┴────┴───┴───┴───┴───┴───┘
      
  4. y = x;

    1. 代码含义:将变量 y 的值赋为变量 x 的值。

    2. JVM 操作:找到变量 y 的存储单元,移除原来的值 1,放入新的值 10(还包含查找 x = 10 的过程)。

             x        y
             │        │
             ▼        ▼
      ┌───┬────┬───┬────┬───┬───┬───┐
      │   │ 10 │   │ 10 │   │   │   │
      └───┴────┴───┴────┴───┴───┴───┘
      

2、数据类型

2.1、基本类型

2.1.1、八大类型

基本数据类型:CPU 可直接进行运算的类型。

含义 内存(byte) 范围 默认值
byte 字节 1 [-27 , 27 -1] 0
short 短整型 2 [-215, 215 - 1] 0
int 整型 4 [-231, 231 - 1] 0
long 长整型 8 [-263, 263 - 1] 0
float 单精度浮点型 4 [1.4 * 10-45, 3.4 * 1038] 0.0
double 双精度浮点型 8 [4.9 * 10-324, 1.79 * 10308] 0.0
char 字符 2 [0, 216 - 1] ''
boolean 布尔 理论 1bit,实际通常 4byte false

2.1.2、示例

  1. 整数类型

    // byte
    byte num1 = -100;
    
    // short
    short num2 = 300;
    
    // int
    int num3 = 200_000_000;
    
    // long:赋值需要以 L 结尾
    long num4 = 1L;
    
  2. 浮点数类型

    // float:赋值需要以 F 结尾
    float num5 = -1.0F;
    
    // double
    double num6 = 3.14;
    
  3. 字符型与布尔型

    // char:以单引号赋值,即使是空字符
    char ch1 = 'A';
    char ch2 = '好';
    char ch3 = '';
    
    // boolean
    boolean flag = true;
    boolean isGreater = 10 > 9;
    

2.2、引用类型

除了八大基本类型,其它都是引用类型(如 String 字符串类型)。

引用类型的两个重要概念是变量示例

  1. 变量:存放在中,内部存储了对象实例在堆中的内存地址。

  2. 实例:存放在中。

    // 格式
    引用类型 变量名 = new 对象实例();
    
    // 示例
    Object obj = new Object();
    

2.3、说明

2.3.1、字符

char(character):字符,基本类型。

  1. 变量形式单引号 '' 包围。
  2. 底层实现:Java 使用 Unicode 表示中/英文字符,一个 char 占用 2 个字节。

相关操作

  1. 赋值整数:将 char 值赋值给整数变量,值为 char 值对应的十进制 Unicode 编码。

    char ch1 = 'A';
    char ch2 = '好';
    
    int num1 = ch1;   // 65
    int num2 = ch2;	  // 22909
    
  2. Unicode 表示:可用转义字符 \u 结合十六进制 Unicode 编码表示字符。

    char ch1 = '\u0041';	// A
    char ch2 = '\u597D';	// 好
    

2.3.2、常量

常量:需要显式初始化,并且无法再次赋值,否则报错。

  1. 定义:定义变量时使用 final 修饰符。
  2. 作用:提前声明变量名,以此避免在代码中使用魔法值(Magic Number)

2.3.3、作用域

概念

  1. 语句块:Java 中使用 {} 包围语句块,作为一组完整代码(如类、方法、控制语句)。
  2. 作用域:从变量的声明位置开始,到变量所在语句块结束

最佳实践

  1. 尽量将变量的作用域最小化
  2. 避免使用重复的变量名。

2.3.4、var

var 关键字:省略变量类型,由编译器自动推断。

// 示例
var sb = new StringBuilder();
// 编译器自动推断为以下语句
StringBuilder sb = new StringBuilder();

3、运算

3.1、整数运算

整数:表示的是精确的数,其运算结果也是精确的整数。

3.1.1、基本运算符

  1. 运算符:加 +,减 -,乘 *,除 /,取余 %

    1. 除法 / 结果取整数部分,取余 % 结果取余数部分。

    2. 除数若为 0,编译通过但运行时报错。

      java.lang.ArithmeticException: / by zero
      
  2. 运算符简写

    1. 符号+=-=*=/=%=

    2. 使用

      x += 10;
      // 等价于
      x = x + 10;
      
  3. 自增/自减:本质也是运算符简写。

    1. 符号++--

    2. 使用:符号可以在变量之前或之后,其位置表示自增的顺序,会影响运算结果

      • 符号在前:先自增,后引用。

      • 符号在后:先引用,后自增。

        int x = 1;
        int y = 2;
        
        // 情况1:y先自增成3,后引用;x=3+10=13
        x = ++y + 10;
        // 情况2:先引用y,x=2+10=12;后y自增成3
        x = y++ + 10;
        

3.1.2、特殊运算符

① 移位运算

将十进制整数对应的二进制数进行移动。

  1. 左移<<

  2. 右移>>符号位不会移动

  3. 无符号右移>>>(符号位也移动,高位自动补 0)

    // 右移
    int n = -536870912; // 11100000 00000000 00000000 00000000 = -536870912
    int a = n >> 1;  	// 11110000 00000000 00000000 00000000 = -268435456
    int b = n >> 2;  	// 11111000 00000000 00000000 00000000 = -134217728
    int c = n >> 28; 	// 11111111 11111111 11111111 11111110 = -2
    int d = n >> 29;	// 11111111 11111111 11111111 11111111 = -1
    
    // 无符号右移
    int n = -536870912; // 11100000 00000000 00000000 00000000 = -536870912
    int a = n >>> 1;  	// 01110000 00000000 00000000 00000000 = 1879048192
    int b = n >>> 2; 	// 00111000 00000000 00000000 00000000 = 939524096
    int c = n >>> 29; 	// 00000000 00000000 00000000 00000111 = 7
    int d = n >>> 31; 	// 00000000 00000000 00000000 00000001 = 1
    
    // 对byte和short进行位移时,会先转换为int
    // 本质:左移即 * 2,右移即 / 2
    

② 位运算

将整数对应的二进制数按位对齐,依次运算

也称按位运算。

  1. :全 1 才 1。
  2. :有 1 则 1。
  3. :01 互换。
  4. 异或:同 0 异 1。

3.1.3、说明

① 运算符优先级

  1. ():优先级最高,可用来改变运算顺序,提高可读性。
  2. ! ~ ++ --
  3. * / %
  4. + -
  5. << >> >>>
  6. &
  7. |
  8. += -= *= /= %=

② 溢出

溢出:若运算结果超过了整数范围,不会报错,但会导致溢出。

  1. 原因:程序将十进制整数转换为二进制进行运算,当运算结果超过范围时,最高位从 0 变成 1,导致符号改变
  2. 解决方案改用更大范围的整数类型,如 int 改成 long。

③ 类型转换

  1. 类型自动提升:若参与运算的两个数类型不一致,较小类型自动提升为较大类型

    short num1 = 1;
    int num2 = 10;
    
    // short先自动转型为int,再参与运算
    System.out.println(num1 + num2);
    
  2. 强制转型:使用 (类型)较大类型强制转为较小类型(可能产生错误结果)。

    // 正确
    int num1 = 10;
    short num2 = (short) num1; // 10
    
    // 错误:num1超出short范围,强制转型时丢弃2个高位字节
    int num1 = 12345678;
    short num2 = (short) num1; // 24910
    

3.2、浮点数运算

浮点数:通常无法精确表示,其运算结果也是如此。

3.2.1、运算符

整数 浮点数
四则运算
取余
运算符简写 ✔(不包含 %=
自增/自减
移位运算
位运算

3.2.2、说明

① 误差

  1. 由于浮点数无法精确表示,因此容易产生误差。

    double num1 = 1.0 / 10;
    double num2 = 1 - 9.0 / 10;
    
    // 观察x和y是否相等
    System.out.println(x);
    System.out.println(y);
    
  2. 由于误差的存在,判断浮点数是否相等的依据是两数之差小于一个很小的数(而不是使用 =)。

    // 二者之差的绝对值
    double diff = Math.abs(x - y);
    
    if (r < 0.00001) {
        // 认为相等
    }
    

② 溢出

  1. 结论:整数运算 / 0 会报错,浮点数运算 / 0 不会报错

  2. 原因IEEE-754 规定浮点数 /0 结果需要是 NaN(Not a Number)或 Infinity(无穷大)。

    // Java中浮点数/0的三种情况
    double num1 = 0.0/0;	// NaN
    double num2 = 1.0/0;	// Infinity
    double num2 = -1.0/0	// -Infinity
    

③ 类型转换

  1. 类型自动提升:整数与浮点数参与同一则运算时,整数通常会自动转型为浮点型。

    // 情况1:num自动转型
    int num = 1;
    System.out.println(24.1 / num); // int自动转为double,再参与运算
    
    // 情况2:num1不会自动转型
    int num1 = 20, num2 = 4;
    System.out.println(3.4 + num1 / num2); // num1和num2整数运算得5,5会自动转型为double
    
  2. 强制转型:浮点数可以强制转型为整数。

    1. 向下取整:强制转型时,浮点数的小数部分会被丢弃。

    2. 四舍五入:强制转型之前,对浮点数加上 0.5 即可实现四舍五入的效果。

    3. 若转型后超出整型的最大范围,将返回该整型的最大值。

      // 丢弃小数部分
      int n1 = (int) -3.4; // -3
      int n2 = (int) 5.7;  // 5
      
      // 四舍五入:转型前+0.5
      int n3 = (int) (5.7 + 0.5); // 6
      
      // 超出范围:自动返回最大值
      int n4 = (int) 1.2e20; // 2147483647
      

3.3、布尔运算

布尔运算:一种关系运算,结果只有 true 和 false。

3.3.1、运算符

  1. 比较运算符>>=<<===!=

  2. 逻辑运算符

    1. &, &&

    2. |, ||

    3. !

      boolean flag1 = 1 > 2;	// false
      boolean flag2 = 2 >= 1; // true
      
      boolean flag3 = flag1 && flag2;	// false
      boolean flag4 = flag1 || flag2;	// true
      boolean flag5 = !flag4;			// false
      
  3. 三目运算符:根据布尔表达式的结果,返回后续两个表达式之一的计算结果。

    1. 格式布尔表达式 ? 表达式1 : 表达式2

    2. 示例

      // 取两数中的最大值
      int num1 = 20;
      int num2 = 10;
      
      int result = num1 >= num2 ? num1 : num2;
      

3.3.2、短路运算

短路运算:若布尔运算的表达式能提前确定结果,则不会判断后续条件,直接返回结果

  1. 短路运算符&&||

  2. 优点:提高性能。

    // 非短路运算:计算后面的表达式时报错
    boolean result1 = false & (7 / 0 > 1);
    
    // 短路运算:第一个false可确定结果为false,直接返回结果,不会报错
    boolean result2 = false && (7 / 0 > 1);
    

3.3.3、运算符优先级

  • !
  • >>=<<=
  • ==!=
  • &&
  • ||
posted @ 2022-12-19 08:07  Jaywee  阅读(67)  评论(0编辑  收藏  举报

👇