章节2-Java基础

129 阅读10分钟
标识符
  • 定义:程序员有权力自定义名字的部分

  • 规则

    1. 由字母、数字、下划线、$ 组成
    2. 不能以数字开头
    3. 不能是Java中的关键字
    4. 区分大小写
  • 规范(驼峰命名法)

    1. 类名、接口名、枚举、注解:首字母大写且后续单词首字母大写
    2. 方法名、变量名:首字母小写,后续单词首字母大写
    3. 常量名:全部大写,单词之间用下划线隔开
    4. 包名:全部小写
关键字
  • 定义:Java中自带的/自定义的名字
字面量
  • 定义:程序中可以直接使用的数据 ,不需要进行计算或转换。注:字面量的类型决定了它可以被赋值给哪种类型的变量。
变量
  • 定义:变量是内存的一块空间,每定义一个变量,就是在分配内存中的空间。分配变量空间大小通过数据类型决定。
  • 变量三要素:
    • 数据类型:控制分配内存空间的大小
    • 变量名:通过名找值
    • 变量值:变量中(内存空间中)具体数据
源码反码补码
  • bit(比特):计算机中最小的存储单位,只有0、1。一个二进制位称为一个bit
  • byte(字节):计算机存储和数据处理的最小单位,八个bit(比特)组成一个byte(字节)。由于在计算机底层中第一位表示正负数(0为正,1为负),则一个字节最大值为01111111 = 127。
  • 反码补码原码:
    • 在计算机底层中,都是采用补码的形式表示的。
    • 正数的原码反码补码都是相同的,及127补码:01111111
    • 负数的补码运算规则:
      • 将该数的绝对值转化为二进制后最高位改为1。
      • 将转化后的二进制数除符号位(最高位)不变,其他位取反。及-6的原码:10000110 转为反码:11111001
      • 将转换后的反码加1,则获取改负数的补码。及-6的原码:10000110 转为反码:11111001 转为补码:11111010
      • -128的原码与补码都是10000000 即一个字节的取值范围是 -128 ~ 127 一共有256个数据 即2的8次方
数据类型
  • 整型数据类型:byte(1字节)、short(2字节)、int(4字节)、long(8字节)

    • 整型数据类型默认为int型
    • 数据类型赋值规则:先分配空间(基本数据类型直接分配栈的内存空间),再赋值。例:long a = 16; 编译器识别16为整型数据,则自动默认为int数据类型,开辟对应空间,然后再赋值给a变量。 注意点:int数据类型,则声明byte b = 17; 会产生自动类型转换
    • byte、short、char两个数据类型进行各种运算时,会自动转换为int数据类型 即运算结果赋值时,需要使用int数据类型。
    • long数据类型需要加上后缀L。
  • 浮点数据类型:float(4字节)、double(8字节)

    • 默认为double类型
    • 声明float数据类型是需要加上后缀F
    • float数据类型占用空间范围比long数据类型大,因为float数据类型分为整数与小数部分,两个部分是单独计算的(指数的形式)
    • 浮点类型数据在计算机中的存储方式是取其近似值,所以当浮点型数据类型进行运算时,也只能获取近似值,不是精确值。
  • 布尔数据类型:boolean(2字节)

  • 字符数据类型:char(2字节)

    • //当char数据进行运算时,会自动转换为int类型
              System.out.println('a'+1);  //98
      //当'a'+1运算完成后的得到的值为:98  然后再将98复制到字符型a中  则会自动转换为字符型,则输出 b
              char a = 'a'+1;
              System.out.println(a);  //b
      
  • 多学一招:强制类型转换精度损失原理

    • 计算机底层存储二进制数据,都是以补码存放与计算的,所以,当进行强制类型转换时流程为:
      • 1、将该数转化为补码进行底层计算
      • 2、当强制类型转换完成后(也就是剪切掉转换后补码的前三个字节),生成的二进制码会再次被认为是原码
      • 3、将剪切后的二进制原码再次转化为补码进行输出,即可以得到强制类型转换后的数据
    • /**
       * 案例1:
       * byte a=(byte) -129;
       * System.out.println(a);
       */
      System.out.println(Integer.toBinaryString(129));  //原码等于补码:00000000 00000000 00000000 10000001
      System.out.println(Integer.toBinaryString(-129)); //等于输出:System.out.println(0b11111111111111111111111101111111);
      //负数原码等于正数最高位取反:  11111111 11111111 11111111 10000001
      //负数反码等于子数据取反:     11111111 11111111 11111111 01111110
      //补码等于子数据+1:          11111111 11111111 11111111 01111111
      
      //开始剪切
      System.out.println(0b01111111); //127
      //剪切后当作原码开始转化为补码:01111111:此数最高位是0,为正数,所以需要转化为反码:01111111  补码:01111111  == 127
      
      byte a=(byte) -129;
      System.out.println(a); //127
      
      System.out.println("***********************");
      
      /**
       * 案例二:
       * byte b=(byte)  129;
       * System.out.println(b);
       */
      System.out.println(Integer.toBinaryString(127));  //原码等于补码:00000000 00000000 00000000 01111111
      System.out.println(Integer.toBinaryString(-127)); //等于输出:System.out.println(0b11111111111111111111111110000001);
      //负数原码等于正数最高位取反:  11111111 11111111 11111111 01111111
      //负数反码等于子数据取反:     11111111 11111111 11111111 10000000
      //补码等于子数据+1:          11111111 11111111 11111111 10000001
      
      //开始剪切
      System.out.println(0b10000001); //129
      //剪切后当作原码开始转化为补码:10000001:此数最高位是1,为负数,所以需要转化为反码:11111110  补码(一个字节,最高位为符号位):11111111  == -127
      
      byte b=(byte)  129;
      System.out.println(b); //-127
      
运算符
  • 自加与自减运算符

    • ++在前: 先运算后赋值

    • ++在后: 先赋值再运算

    • int a = 10;
      int b = ++a;    //b11  a11
      int c = a++;    //c11  a12
      
  • 字节码解读

    • 在Java语言中, 任何一个方法执行时, 都会专门为这个方法分配所属的内存空间, 供这个方法使用. 每个方法都有自己独立的内存空间, 这个内存空间中有两块不同的内存空间:

    • 局部变量表(存储局部变量的)

    • 操作数栈(存储程序运行过程中参与的运算数据)

image-20241101134754415.png

  • /**
     * 解读字节码文件
     * 住: 读取字节码文件命令 javap -c ReadClass.class
     *
     * 在Java语言中, 每个方法的执行都会为这个方法分配所属的内存空间,这空间分为两个不同的空间
     *         1, 局部变量表(存放局部变量的)
     *         2, 操作数栈(存储程序运行过程中参与的运算数据)
     */
    public class ReadClass {
        public static void main(String[] args) {
            int a = 10;
            int b = a++;
    
        }
    
        /*
            public static void main(java.lang.String[]);
            Code:
            0: bipush        10     //在操作数栈中分配一个int空间存放10这个数据
            2: istore_1             //将操作数栈中的栈顶push到局部变量表的1号槽位
            3: iload_1              //将局部变量表中1号槽位的值复制一份到操作数栈中
            4: iinc          1, 1   //将局部变量表中一号槽位加1
            7: istore_2             //将操作数栈中的栈顶push到局部变量表的2号槽位
            8: return
         */
    }
    
  • 扩展赋值运算符的使用 (+= -= …)

    • 注意点: 使用扩展赋值运算符时会自动执行强制类型转换

    • double a = 11.2;
      int b = 10;
      b += a;   //不报错
      b = a + b;  //编译报错
      System.out.println(b);  //21
      
流程控制语句
  • if语句

  • switch

    • //基本格式
      int week = 1;
      switch (week) {
          case 1:
              System.out.println("星期一");
              break;
          case 2:
              System.out.println("星期二");
              break;
          default:
              System.out.println("您的输入有误, 请检查!");
              break;
      }
      
    • 注意事项:

      • switch后面可以接收的数据类型

        • 基本数据类型: byte, short, int, char
        • 引用数据类型: String, 枚举
      • 当 switch 语句, 省略了break, 将会开启case穿透现象

      • JDK14版本新特性: case后面允许编写多个值, 中间使用逗号分隔

      • switch (num) {
                    case 1, 2, 3, 4, 5:
                        System.out.println("工作日");
                        break;
                    case 6, 7:
                        System.out.println("休息日");
                        break;
                    default:
                        System.out.println("您的输入有误!");
                        break;
                }
        
  • for循环

    • for 循环体中的数据会循环执行一次,清除上次循环的数据,而小括号中的变量随着 for 循环执行结束而清除
  • while循环

  • do...while循环

    • 先执行一次程序, 再判断是否可以继续执行
  • break

    • break 在嵌套循环内循环中,只控制内循环结束,若需要控制外循环结束,需要使用标号(给循环命名,格式 --> 循环名:)

    • lo:
      for (int i = 1; i <= 3; i++) {
          for (int j = 1; j <= 5; j++) {
              if(j == 2){
                  break lo;
              }
              System.out.println("HelloWorld");
          }
      }
      
      
      数组
  • 概述

    • 在Java中, 存储相同数据类型的不可变的容器 无标题.png
  • 优点: 超强的查找能力-->O(1)

    • 由于在Java中, 数组只能存储相同数据类型的数据且是连续的, 即每一个数组占用的空间都是一致的, 当获取到数组的索引后, 即可以通过索引与所存储的数据类型大小直接计算出需要查找的内存地址直接定位, 所以数组的查询空间复杂度为O(1) , 不管数组的长短, 查询的时间是一致的.
  • 缺点:

    • 由于是连续存储,所以数组对增删操作会耗费很多时间, 因为进行增删操作时, 为保证连续存储的特性, 会导致后续所有的数据进行移位, 以保证数据连续性
    • 不能存储大量数据. 因为在内存中很难由一块很大且连续的地址
  • 使用随机数创建元素唯一的数组

  •                public static int getValue(int inputNum, int[] arr, int i) {
                   ​
                       Random random = new Random();
                       Integer num = inputNum;
                   ​
                       for (int j = 0; j < i; j++) {
                           if (inputNum == arr[j]) {
                               num = null;
                               break;
                           }
                       }
                   ​
                       if (num == null) {
                           return getValue(random.nextInt(10), arr, i);
                       }
                   ​
                       return inputNum;
                   }
                   ​
                   public static void addArrValue(int[] arr) {
                   ​
                       Random random = new Random();
                       for (int i = 0; i < arr.length; i++) {
                           int inputNum = random.nextInt(10);
                           arr[i] = getValue(inputNum, arr, i);
                       }
                   }
                   ​
                   /*
                   方法一:使用递归
                   */
                   @Test
                   public void test01() {
                       int[] arr = new int[10];
                   ​
                       addArrValue(arr);
                   ​
                       for (int item : arr) {
                           System.out.print(item + " ");
                       }
                   }
                   ​
                   /*
                   方法一:使用循环
                   */
                   @Test
                   public void test02() {
                       int[] arr = new int[10];
                   ​
                       Random random = new Random();
                   ​
                       for (int i = 0; i < arr.length; i++) {
                           arr[i] = random.nextInt(10);
                           for (int j = 0; j < i; j++) {
                               if (arr[i] == arr[j]) {
                                   i--;
                               }
                           }
                       }
                   ​
                       for (int item : arr) {
                           System.out.print(item + " ");
                       }
                   }