Java 基础
Java 基础

Java 基础

Java程序的基本结构

  • 包声明

    package <包名>;
    
  • 导入语句

    import <包名>.<类名>;   // 导入特定类
    import <包名>.*;        // 导入整个包
    
  • 类定义

    public class Main {
        // 类体
    }
    
  • 主方法

    public static void main(String[] args) {
        // 程序代码
    }
    

语法基础

  1. 标识符

    用来标识类名、变量名、方法名、类型名、数组名、文件名的有效字符序列称为标识符。简单地说,标识符就是一个名字。

    Java语言规定标识符由字母、下划线、美元符号和数字组成,并且第一个字符不能是数字。标识符中的字母是区分大小写的。

  2. 关键字

    关键字就是Java语言中已经被赋予特定意义的一些单词。

    功能分类 关键字
    访问控制 private、protected、public
    类、方法和变量修饰符 abstract、class、enum、extends、final、implements
    程序控制 interface、native、new、static、strictfp、synchronized、transient、volatile
    错误处理 break、continue、return、do、while、if、else、for
    包相关 instanceof、switch、case、default
    基本数据类型 assert、try、catch、finally、throw、throws
    变量引用 package、import
    保留字 boolean、byte、char、double、float、int、long、short
  3. 基本数据类型

    数据类型 关键字 占用位数 取值范围/值域
    布尔型 boolean 8位 true, false
    字符型 char 16位 ‘\u0000’~’\uFFFF’ (0~65535)
    字节型 byte 8位 -128~127
    短整型 short 16位 -32768~32767
    整型 int 32位 -2,147,483,648~2,147,483,647
    长整型 long 64位 -2⁶³~2⁶³-1
    浮点型 float 32位 1.40129846432481707e-45~3.40282346638528860e+38
    双精度型 double 64位 4.94065645841246544e-324~1.79769313486231570e+308

    数据精度(由低至高):byte \to short \to int \to long \to float \to double

    • 基本数据类型的转换

      当把级别低的变量的值赋给级别高的变量时,系统自动完成数据类型的转换。

      当把级别高的变量的值赋给级别低的变量时,必须使用显示类型转换运算。显示转换的格式:

      (<数据类型>)<数值>
      
  4. 运算符

    1. 算术运算符

      运算符 描述 示例
      + 加法 a + b
      - 减法 a - b
      * 乘法 a * b
      / 除法 a / b
      % 取模(余数) a % b
      ++ 自增 a++++a
      -- 自减 a----a

      注意++a (前缀) 和 a++ (后缀) 的区别在于表达式的值不同。

    2. 关系运算符

      运算符 描述 示例
      == 等于 a == b
      != 不等于 a != b
      > 大于 a > b
      < 小于 a < b
      >= 大于或等于 a >= b
      <= 小于或等于 a <= b
    3. 逻辑运算符

      运算符 描述 示例
      && 逻辑与 a && b
      || 逻辑或 a || b
      ! 逻辑非 !a

      短路特性&&|| 具有短路特性,即如果第一个操作数已经能确定结果,则不会计算第二个操作数。

    4. 位运算符

      运算符 描述 示例
      & 位与 a & b
      | 位或 a | b
      ^ 位异或 a ^ b
      ~ 位非 ~a
      << 左移 a << b
      >> 右移(带符号) a >> b
      >>> 右移(无符号) a >>> b
    5. 赋值运算符

      运算符 描述 示例 等价于
      = 赋值 a = b
      += 加后赋值 a += b a = a + b
      -= 减后赋值 a -= b a = a - b
      *= 乘后赋值 a *= b a = a * b
      /= 除后赋值 a /= b a = a / b
      %= 取模后赋值 a %= b a = a % b
      &= 位与后赋值 a &= b a = a & b
      |= 位或后赋值 a |= b a = a | b
      ^= 位异或后赋值 a ^= b a = a ^ b
      <<= 左移后赋值 a <<= b a = a << b
      >>= 右移后赋值 a >>= b a = a >> b
      >>>= 无符号右移后赋值 a >>>= b a = a >>> b
    6. 条件运算符

      <条件> ? <表达式1> : <表达式2>

输入输出

  1. 输出

    System.out.printf("<格式字符串>",<参数>);   //格式化输出
    System.out.print(<基本类型或对象>);    //普通输出
    System.out.println(<基本类型或对象>);    //换行输出
    
  2. 输入

    • 导入 Scanner 类
    import java.util.Scanner;
    
    • 创建 Scanner 对象
    Scanner scanner = new Scanner(System.in); 
    
    • 读取不同类型的数据

      方法 描述 示例
      next() 读取下一个字符串(以空格分隔) String s = scanner.next();
      nextLine() 读取一行文本 String line = scanner.nextLine();
      nextInt() 读取下一个整数 int num = scanner.nextInt();
      nextDouble() 读取下一个双精度浮点数 double d = scanner.nextDouble();
      nextBoolean() 读取下一个布尔值 boolean b = scanner.nextBoolean();
      hasNext() 检查是否还有输入 while(scanner.hasNext()) {...}
    • useDelimiter 方法

      useDelimiter() 是 Scanner 类的一个重要方法,用于设置输入的分隔模式,可以灵活地控制如何将输入内容分割成多个 token。

      Scanner useDelimiter(String pattern)
      Scanner useDelimiter(Pattern pattern)
      
      • pattern:可以是一个字符串形式的正则表达式,或者是一个预编译的 Pattern 对象
      • return:Scanner 对象
      1. 使用字符串作为分隔符

        scanner.useDelimiter(","); // 使用逗号作为分隔符
        while(scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        
      2. 使用正则表达式作为分隔符

        scanner.useDelimiter("\\d+"); // 使用数字作为分隔符
        while(scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        
      3. 使用多个分隔符

        scanner.useDelimiter(" and | or "); // 使用" and "或" or "作为分隔符
        while(scanner.hasNext()) {
            System.out.println(scanner.next());
        }
        

数组

  1. 数组声明

    // 声明方式1:推荐
    <数据类型>[] <数组名>;  
    
    // 声明方式2:合法但不推荐
    <数据类型> <数组名>[];  
    
  2. 初始化

    • 静态初始化

      <数据类型>[] <数组名> = {<元素1, 元素2, ...>};    //一维数组
      <数据类型>[][] <数组名> = {{<1行元素>},{<2行元素>},...};    //二维数组
      
    • 动态初始化

      <数据类型>[] <数组名> = new <数据类型>[<长度>];    //一维数组
      <数据类型>[][] <数组名> = new <数据类型>[<行数>][<列数>];    //二维数组
      
    • 访问元素

      <数组名>[<索引>]    //一维数组
      <数组名>[<行索引>][<列索引>]    //二维数组
      
    • 数组长度

      <数组名>.length
      

语句应用

  1. 分支语句

    • if 语句

      if (<条件表达式>) {
          // 条件为 true 时执行的代码
      }
      
      if (<条件表达式>) {
          // 条件为 true 时执行的代码
      } else {
          // 条件为 false 时执行的代码
      }
      
      if (<条件1>) {
          // 条件1为 true 时执行的代码
      } else if (<条件2>) {
          // 条件2为 true 时执行的代码
      } else {
          // 所有条件都为 false 时执行的代码
      }
      
    • switch 语句

      switch (<表达式>) {
          case <1>:
              // 代码块1
              break;
          case <2>:
              // 代码块2
              break;
          // 可以有任意数量的 case 语句
          default:
              // 默认代码块
      }
      
  2. 循环语句

    • while 循环

      while (<条件表达式>) {
          // 循环体
      }
      
    • do-while 循环

      do {
          // 循环体
      } while (<条件表达式>);
      
    • for 循环

      for (<初始化>; <条件判断>; <迭代更新>) {
          // 循环体
      }
      
    • 增强 for 循环 (for-each)

      for (<元素类型> <变量名> : <数组或集合>) {
          // 循环体
      }
      
  3. 中断流程控制

    • break 语句

      立即终止当前循环或 switch 语句。

      break;
      

      带标签的 break,跳出指定的外层循环。

      <标签名>: // 标签
      <循环语句>{
          // 循环体
          <循环语句>{
              // 循环体
              break <标签名>; // 直接跳出外层循环
          }
      }
      
    • continue 语句

      跳过当前循环的剩余部分,直接进入下一次循环。

      continue;
      

      跳转到指定标签的循环的下一次迭代。

      <标签名>: // 标签
      <循环语句>{
          // 循环体
          <循环语句>{
              // 循环体
              break <标签名>; // 跳过外层循环的当前迭代
          }
      }
      
    • return 语句

      用于从方法中返回,可以带返回值(对于非void方法)或不带返回值(对于void方法)。

      return [<返回值>];
      

面相对象

  1. 修饰符

    • 访问修饰符
      • public:所有类均可访问
      • protected:同包或子类可访问
      • 默认(无):同包可访问
      • private:仅本类可访问
    • 其他修饰符
      • final:类不能被继承
      • abstract:抽象类,不能实例化
      • static:静态嵌套类(内部类)
      • strictfp:浮点运算严格遵守IEEE 754标准
  2. 类的定义

    [<访问修饰符>] [<修饰符>] class <类名> [extends <父类>] [implements <接口列表>] {
        // 成员变量(字段)
        // 构造方法
        // 成员方法
        // 初始化块
        // 内部类/接口
    }
    
  3. 成员变量

    [<访问修饰符>] [static/final/transient/volatile] <数据类型> <变量名> [= <初始值>];
    
  4. 成员方法

    [<访问修饰符>] [static/final/abstract] <返回类型> <方法名>([<参数列表>]) [throws <异常列表>] {
        // 方法体
        [return <返回值>;]
    }
    
    • 返回类型

      • 基本类型/引用类型:返回具体值
      • void:无返回值
      • 可以是泛型类型
    • 参数传递

      • ​值传递​​:基本类型传递值副本
      • ​引用传递​​:对象传递引用副本
    • 方法重载
      方法重载是指在同一个类中,允许存在多个同名方法,只要它们的​​参数列表不同​​(参数类型、参数个数或参数顺序不同)。

      • 方法名必须相同
      • 参数列表必须不同(至少一项不同)
      • 返回类型可以相同也可以不同
      • 访问修饰符可以相同也可以不同
      • 可以抛出不同的异常
  5. 构造方法

    [<访问修饰符>] <类名>([<参数列表>]) {
        // 初始化代码
    }
    
  6. this关键字

    • 当成员变量与局部变量同名时,使用this可以明确指定访问的是成员变量:

      this.<变量名>
      
    • 在构造方法中,可以使用this()调用本类的其他构造方法,必须放在构造方法的第一行:

      [<访问修饰符>] <类名>([<参数列表>]) {
          this(<参数列表>);
      }
      
    • 返回当前对象:

      return this;
      

对象

  1. 对象的创建

    <类名> <对象名> = new <构造方法>([<参数>]);
    
  2. 对象的使用

    • 访问成员变量

      <对象名>.<变量名>;
      
    • 调用成员方法

      <对象名>.<方法名>([<参数>]);
      

继承

  1. 定义语法

    class 子类 extends 父类 {
        // 子类特有的属性和方法
    }
    
  2. 访问权限

    修饰符 本类 同包 子类 其他
    private
    默认
    protected
    public
  3. 方法重写

    class <父类> {
        [<访问修饰符>] [static/final/abstract] <返回类型> <方法名>([<参数列表>]) [throws <异常列表>] {
            // 方法体
        }
    }
    
    class <子类> extends <父类> {
        @Override
        [<访问修饰符>] [static/final/abstract] <返回类型> <方法名>([<参数列表>]) [throws <异常列表>] {
            // 方法体
        }
    }
    
  4. super关键字

    • 当子类和父类有同名成员变量时,使用super可以访问父类的变量:

      super.<>变量名
      
    • 当子类重写了父类方法时,可以使用super调用父类的原始方法:

      super.<方法名>([<参数列表>]);
      
    • 在子类构造方法中使用super()调用父类构造方法,必须放在子类构造方法的第一行:

      [<访问修饰符>] <类名>([<参数列表>]) {
          super(<参数列表>);
      }
      

多态

  1. 形式

    <父类类型> <变量名> = new <子类类型>();
    
  2. 向上转型

    <父类类型> <引用名> = new <子类类型>();
    
  3. 向下转型

    <子类类型> <引用名> = (<子类类型>)<父类引用>;
    

抽象类

  1. 抽象类定义

    [<访问修饰符>] abstract class <类名> {
        // 成员变量
        // 构造方法
        // 抽象方法
        // 具体方法
    }
    
  2. 抽象方法

    [<访问修饰符>] abstract <返回类型> <方法名>([<参数列表>]);
    
    • 抽象方法​​必须存在于​​抽象类​​或接口中

接口

  1. 接口定义

    [访问修饰符] interface 接口名 {
        // 常量声明
        // 抽象方法
        // 默认方法
        // 静态方法
        // 私有方法
    }
    
    • 不能直接创建对象
    • 可以包含抽象方法、默认方法、静态方法和私有方法
    • 可以包含常量(public static final)
    • 支持多重实现(一个类可以实现多个接口)
  2. 方法

    • 抽象方法

      [public] [abstract] <返回类型> <方法名>([<参数列表>]);
      
      • 默认修饰符:public abstract(可省略)
      • 没有方法体
      • 实现类必须重写所有抽象方法
    • 默认方法

      [public] default <返回类型> <方法名>([<参数列表>]) {
          // 方法体
      }
      
      • 使用default关键字
      • 有方法实现
      • 实现类可选择重写或直接继承
    • 静态方法

      [public] static <返回类型> <方法名>([<参数列表>]) {
          // 方法体
      }
      
      • 使用static关键字
      • 有方法实现
      • 只能通过接口名调用
    • 私有方法

      private 返回类型 方法名([参数列表]) {
          // 方法体
      }
      
  3. 常量

    //(public static final可省略)
    [public] [static] [final] <数据类型> <常量名> = <>;
    
    特性 常量 抽象方法 默认方法 静态方法
    关键字 (无) (无) default static
    默认修饰符 public static final public abstract public public
    实现 必须初始化 无实现 有实现 有实现
    调用方式 接口名.常量名 实现类实例调用 实现类实例调用 接口名.方法名()
    可被重写 必须 可选
  4. 接口的实现

    • 类实现接口

      class <类名> implements <接口1>[, <接口2>, ...] {
          // 必须实现所有抽象方法(除非是抽象类)
      }
      
    • 接口继承接口

      interface <子接口> extends <父接口1>[, <父接口2>, ...] {
          // 可以添加新方法
      }
      

内部类

  1. 成员内部类

    [<访问修饰符>] class <外部类> {
        // 外部类成员
        
        class <内部类> {
            // 内部类成员
        }
    }
    
  2. 匿名内部类

        <类名> <对象名> = new <类名>(<参数列表>) {
            // 类体
        }
    

常用类

  1. String类

    • 创建 String 对象

      String <变量名> = "<字符串内容>";                    // 直接赋值
      String <变量名> = new String("<字符串内容>");        // 构造方法创建
      char[] <字符数组名> = {'H','e','l','l','o'};
      String <变量名> = new String(<字符数组名>);           // 从字符数组创建
      byte[] <字节数组名> = {72, 101, 108, 108, 111};
      String <变量名> = new String(<字节数组名>);            // 从字节数组创建
      
    • 常用方法

      int <长度变量> = <字符串变量>.length();  // 获取长度
      char <字符变量> = <字符串变量>.charAt(<索引>);   // 获取字符
      int <索引变量> = <字符串变量>.indexOf("<子串>");  // 查找子串位置
      boolean <相等判断> = <字符串1>.equals(<字符串2>);         // 区分大小写比较
      boolean <忽略大小写判断> = <字符串1>.equalsIgnoreCase(<字符串2>);  // 不区分大小写
      int <比较结果> = <字符串1>.compareTo(<字符串2>);        // ASCII码差值
      String <修剪结果> = <原字符串>.trim();      // 去除首尾空格
      String <修剪结果> = <原字符串>.strip();          // 移除首尾空白
      String <大写结果> = <原字符串>.toUpperCase(); // 转大写
      String <小写结果> = <原字符串>.toLowerCase(); // 转小写
      String <替换结果> = <原字符串>.replace('<原字符>', '<新字符>'); // 字符替换
      String[] <分割数组> = <分割字符串>.split("<分隔符>");  // 字符串分割
      String <连接结果> = String.join("<连接符>", <分割数组>);  // 字符串连接
      String <字符串变量> = String.valueOf(<整型变量>);  // 整形转字符串
      
  2. 包装类

    • Integer类(整型包装类)

      • 对象创建

        Integer <变量名> = Integer.valueOf(<整型值>);    // 推荐方式
        Integer <变量名> = Integer.valueOf("<数字字符串>");  // 从字符串创建
        Integer <变量名> = new Integer(<整型值>);        // 已弃用方式
        
      • 类型转换

        int <基本类型变量> = <Integer对象>.intValue();       // 拆箱操作
        String <字符串变量> = <Integer对象>.toString();         // 转字符串
        String <进制字符串> = Integer.toBinaryString(<整型值>);  // 转二进制
        String <进制字符串> = Integer.toHexString(<整型值>);       // 转十六进制
        
      • 字符串解析

        int <整型值> = Integer.parseInt("<数字字符串>");     // 解析十进制
        int <整型值> = Integer.parseInt("<数字字符串>", <进制>);  // 指定进制解析
        Integer <对象> = Integer.decode("<数字字符串>");  // 自动识别进制
        
      • 比较与运算

        int <比较结果> = Integer.compare(<1>, <2>);      // 比较
        boolean <相等判断> = <对象1>.equals(<对象2>);         // 对象比较
        int <求和结果> = Integer.sum(<1>, <2>);           // 求和
        int <最大值> = Integer.max(<1>, <2>);           // 取最大值
        
    • Double类(双精度浮点包装类)

      • 对象创建

        Double <变量名> = Double.valueOf(<双精度值>);     // 推荐方式
        Double <变量名> = Double.valueOf("<数字字符串>");  // 从字符串创建
        Double <变量名> = <双精度值>;                    // 自动装箱
        
      • 类型转换

        double <基本类型> = <Double对象>.doubleValue();  // 拆箱
        String <字符串> = <Double对象>.toString();        // 转字符串
        int <整型值> = <Double对象>.intValue();          // 转int(截断)
        
      • 字符串解析

        double <双精度值> = Double.parseDouble("<数字字符串>");
        String <十六进制> = Double.toHexString(<双精度值>);
        
    • Character类(字符包装类)

      • 对象创建

        Character <变量名> = Character.valueOf('<字符>');  // 推荐方式
        Character <变量名> = '<字符>';                    // 自动装箱
        
      • 字符判断

        boolean <是否字母> = Character.isLetter(<字符>);
        boolean <是否数字> = Character.isDigit(<字符>);
        boolean <是否空白> = Character.isWhitespace(<字符>);
        boolean <是否大写> = Character.isUpperCase(<字符>);
        
      • 字符转换

        char <小写字符> = Character.toLowerCase(<字符>);
        char <大写字符> = Character.toUpperCase(<字符>);
        int <代码点> = Character.codePointAt(<字符数组>, <索引>);
        
    • Boolean类(布尔包装类)

      • 对象创建

        Boolean <变量名> = Boolean.valueOf(<布尔值>);     // 推荐方式
        Boolean <变量名> = Boolean.valueOf("<字符串>");  // 从字符串创建
        Boolean <变量名> = <布尔值>;                    // 自动装箱
        
      • 字符串解析

        boolean <布尔值> = Boolean.parseBoolean("<字符串>");
        Boolean <对象> = Boolean.valueOf("true");  // 不区分大小写
        
  3. ArrayList

    List<<元素类型>> <列表名> = new ArrayList<<元素类型>>();  // 创建ArrayList
    <列表名>.add(<元素>);                               // 添加元素
    <元素类型> <元素变量> = <列表名>.get(<索引>);               // 获取元素
    <列表名>.remove(<索引>);                       // 按索引删除
    <列表名>.remove(<元素>);                       // 按元素删除
    int <大小变量> = <列表名>.size();                     // 获取大小
    
  4. HashMap

    Map<<键类型>,<值类型>> <映射名> = new HashMap<<键类型>,<值类型>>();    // 创建HashMap
    <映射名>.put(<>,<>);                            // 添加键值对
    <值类型> <值变量> = <映射名>.get(<>);                 // 获取值
    <映射名>.remove(<>);                              // 删除键值对
    boolean <存在结果> = <映射名>.containsKey(<>);      // 检查键是否存在