完整教程:Java编程基础:从入门到精通

阶段一:Java 基础与编程思维

一、Java 基础语法(变量、条件、循环、数组)

        变量

  • 定义:用于存储程序运行过程中需要临时保存的数据,需指定 “数据类型 + 变量名”,遵循 “先声明、后使用” 原则。
  • 核心分类
    • 基本数据类型:8 种,分别对应不同数据场景,无需手动回收内存,具体如下:
      类型分类具体类型占用空间应用场景
      整数型byte1 字节存储小范围整数(如年龄、状态码)
      short2 字节中等范围整数(如短 ID)
      int4 字节常用整数(如数量、索引),默认整数类型
      long8 字节大范围整数(如时间戳、大 ID),需加后缀L(如100L
      浮点型float4 字节单精度小数(如粗略计算),需加后缀F(如3.14F
      double8 字节双精度小数(如精确计算:金额、坐标),默认小数类型
      字符型char2 字节单个字符(如'A''中'),用单引号包裹
      布尔型boolean1 位逻辑判断(true/false),常用于条件语句
    • 引用数据类型:如数组、类对象(后续学习的String、集合等),存储的是数据在堆内存中的 “地址”,需手动管理或依赖 GC 回收。
  • 使用规则:变量名需符合 “字母、数字、下划线、$” 组成,且不能以数字开头,建议遵循 “小驼峰命名法”(如userAgetotalScore)。

        条件

  • 定义:根据 “条件是否成立” 执行不同代码分支,解决程序中的 “选择逻辑”(如判断用户权限、数据合法性)。
  • 核心结构
    • if-else:基础条件判断,支持嵌套,适合 1-3 个分支场景。

      // 示例:判断成绩等级
      int score = 85;
      if (score >= 90) {
      System.out.println("优秀");
      } else if (score >= 80) {
      System.out.println("良好");
      } else if (score >= 60) {
      System.out.println("及格");
      } else {
      System.out.println("不及格");
      }
    • switch-case:适合 “固定值匹配” 场景(如菜单选择、状态码处理),JDK 7 + 支持String类型,需注意break(避免穿透)和default(默认分支)。
      // 示例:判断星期几
      String week = "周二";
      switch (week) {
      case "周一":
      case "周二":
      case "周三":
      case "周四":
      case "周五":
      System.out.println("工作日");
      break;
      case "周六":
      case "周日":
      System.out.println("休息日");
      break;
      default:
      System.out.println("输入错误");
      }

        循环

  • 定义:重复执行一段代码,解决 “批量处理” 场景(如遍历数组、统计数据),避免代码冗余。
  • 核心结构
    • for:适合 “已知循环次数” 场景(如遍历固定长度的数组、执行指定次数的操作),结构为 “初始化变量→循环条件→更新变量”。
      // 示例:计算1-10的和
      int sum = 0;
      for (int i = 1; i <= 10; i++) {
      sum += i; // 每次循环累加i
      }
      System.out.println("1-10的和:" + sum); // 输出55
    • while:适合 “未知循环次数,已知循环条件” 场景(如读取用户输入直到输入正确),需先初始化变量,避免死循环。
      // 示例:循环接收用户输入,直到输入数字
      Scanner scanner = new Scanner(System.in);
      int num = 0;
      while (!scanner.hasNextInt()) {
      System.out.println("请输入数字:");
      scanner.next(); // 丢弃非数字输入
      }
      num = scanner.nextInt();
      System.out.println("你输入的数字:" + num);
    • do-while:与while类似,但 “先执行一次循环体,再判断条件”,确保循环体至少执行一次(如菜单交互:先显示菜单,再接收选择)。

        数组

  • 定义:存储 “同类型、固定长度” 的批量数据,通过 “索引”(从 0 开始)访问元素,是后续集合框架的基础。
  • 核心操作
    • 初始化:分 “静态初始化”(已知元素)和 “动态初始化”(已知长度)两种。
      // 静态初始化:直接指定元素,长度由元素个数决定
      int[] scores = {85, 92, 78};
      // 动态初始化:指定长度,元素默认初始化(int默认0,String默认null)
      String[] names = new String[3];
      names[0] = "张三";
      names[1] = "李四";
    • 遍历:通过for循环(普通 / 增强)访问所有元素,增强for循环更简洁(无需关注索引)。
      // 普通for循环:适合需要索引的场景(如修改元素)
      for (int i = 0; i < scores.length; i++) {
      System.out.println("索引" + i + ":" + scores[i]);
      }
      // 增强for循环:适合仅读取元素的场景
      for (String name : names) {
      System.out.println("姓名:" + name);
      }
    • 注意事项:数组长度一旦确定无法修改,若索引超出范围(如访问scores[3],而数组长度为 3),会抛出ArrayIndexOutOfBoundsException(数组越界异常)

二、面向对象编程(类、继承、多态、接口、抽象类)

        类

  • 定义:对 “现实事物” 的抽象描述,包含 “属性”(事物的特征,如用户的姓名、年龄)和 “方法”(事物的行为,如用户的登录、下单),是创建对象的 “模板”。
  • 核心组成
    • 成员变量:定义在类中、方法外,描述对象的属性,默认有初始值(如int默认 0,String默认null)。
    • 成员方法:定义在类中,描述对象的行为,可带参数和返回值,调用时需通过对象实例。
    • 构造方法:用于初始化对象,与类名同名、无返回值,默认提供无参构造;若自定义构造方法,默认无参构造会失效,需手动添加。
  • 示例
    // 定义“用户”类(模板)
    class User {
    // 成员变量(属性)
    private String username; // 私有属性,通过getter/setter访问
    private int age;
    // 构造方法(初始化对象)
    public User(String username, int age) {
    this.username = username; // this表示当前对象
    this.age = age;
    }
    // 成员方法(行为)
    public void showInfo() {
    System.out.println("用户名:" + username + ",年龄:" + age);
    }
    // Getter/Setter(访问私有属性)
    public String getUsername() {
    return username;
    }
    public void setAge(int age) {
    if (age > 0 && age < 150) { // 合法性校验
    this.age = age;
    }
    }
    }
    // 创建对象(实例化)并使用
    public class ClassDemo {
    public static void main(String[] args) {
    User user = new User("张三", 25); // 调用构造方法创建对象
    user.showInfo(); // 调用方法:输出“用户名:张三,年龄:25”
    user.setAge(30); // 修改属性
    System.out.println("修改后年龄:" + user.getUsername() + "," + user.getAge());
    }
    }

        继承

  • 定义:让 “子类” 复用 “父类” 的属性和方法,同时可添加子类专属的属性和方法,实现 “代码复用”,通过extends关键字实现,Java 支持单继承(一个子类只能有一个直接父类)。
  • 核心特性
    • 方法重写(Override):子类对父类的方法进行 “重新实现”,要求方法名、参数列表、返回值类型完全一致,且父类方法不能是private(私有方法无法继承)。
    • super关键字:用于访问父类的属性、方法和构造方法,如super.username访问父类属性,super()调用父类构造方法(需放在子类构造方法第一行)。
  • 示例
    // 父类:动物(通用属性和方法)
    class Animal {
    protected String name; // protected:子类可访问
    public Animal(String name) {
    this.name = name;
    }
    // 父类方法
    public void eat() {
    System.out.println(name + "正在进食");
    }
    }
    // 子类:狗(继承Animal)
    class Dog extends Animal {
    // 子类专属属性
    private String breed;
    // 子类构造方法:必须调用父类构造方法
    public Dog(String name, String breed) {
    super(name); // 调用父类构造方法
    this.breed = breed;
    }
    // 方法重写:重写父类的eat方法
    @Override
    public void eat() {
    System.out.println(name + "(" + breed + ")正在吃狗粮");
    }
    // 子类专属方法
    public void bark() {
    System.out.println(name + "汪汪叫");
    }
    }
    // 测试继承
    public class ExtendDemo {
    public static void main(String[] args) {
    Dog dog = new Dog("旺财", "金毛");
    dog.eat(); // 调用重写后的方法:输出“旺财(金毛)正在吃狗粮”
    dog.bark(); // 调用子类专属方法:输出“旺财汪汪叫”
    }
    }

        多态

  • 定义:“同一行为,不同实现”,即父类引用指向子类对象时,调用方法会执行子类的重写实现,实现代码的 “灵活性” 和 “扩展性”。
  • 实现条件
    1. 存在继承关系(子类继承父类);
    2. 子类重写父类方法;
    3. 父类引用指向子类对象(如Animal animal = new Dog();)。
  • 示例
    // 父类:动物(已定义)
    // 子类:猫(新增子类)
    class Cat extends Animal {
    public Cat(String name) {
    super(name);
    }
    // 重写父类eat方法
    @Override
    public void eat() {
    System.out.println(name + "正在吃猫粮");
    }
    // 子类专属方法
    public void meow() {
    System.out.println(name + "喵喵叫");
    }
    }
    // 测试多态
    public class PolymorphismDemo {
    public static void main(String[] args) {
    // 父类引用指向子类对象(多态核心)
    Animal animal1 = new Dog("旺财", "金毛");
    Animal animal2 = new Cat("咪宝");
    // 调用eat方法:执行子类重写的实现(多态体现)
    animal1.eat(); // 输出“旺财(金毛)正在吃狗粮”
    animal2.eat(); // 输出“咪宝正在吃猫粮”
    // 注意:父类引用无法直接调用子类专属方法(需强制转型)
    if (animal1 instanceof Dog) { // 判断对象类型
    Dog dog = (Dog) animal1; // 强制转型为Dog
    dog.bark(); // 调用子类专属方法:输出“旺财汪汪叫”
    }
    }
    }

        接口

  • 定义:一种 “特殊的抽象类型”,仅包含抽象方法(JDK 8 + 支持默认方法default和静态方法static),用于定义 “方法规范”,强制实现类遵循统一标准,通过implements关键字实现,Java 支持多实现(一个类可实现多个接口)。
  • 核心特性
    • 接口中的方法默认是public abstract(可省略),属性默认是public static final(常量);
    • 实现类必须重写接口中的所有抽象方法,否则实现类需定义为抽象类;
    • 多实现:解决 Java 单继承的限制,一个类可同时实现多个接口,如class Student implements Study, Sports
  • 示例
    // 定义接口1:学习(规范学习行为)
    interface Study {
    void study(); // 抽象方法,默认public abstract
    String COURSE = "Java"; // 常量,默认public static final
    }
    // 定义接口2:运动(规范运动行为)
    interface Sports {
    void doSports(); // 抽象方法
    }
    // 实现类:学生(实现两个接口)
    class Student implements Study, Sports {
    private String name;
    public Student(String name) {
    this.name = name;
    }
    // 重写Study接口的study方法
    @Override
    public void study() {
    System.out.println(name + "正在学习" + Study.COURSE);
    }
    // 重写Sports接口的doSports方法
    @Override
    public void doSports() {
    System.out.println(name + "正在打篮球");
    }
    }
    // 测试接口
    public class InterfaceDemo {
    public static void main(String[] args) {
    Student student = new Student("李四");
    student.study(); // 输出“李四正在学习Java”
    student.doSports(); // 输出“李四正在打篮球”
    }
    }

        抽象类

  • 定义:包含 “抽象方法” 的类,通过abstract关键字定义,无法直接实例化(需通过子类继承并实现抽象方法),用于 “既提供代码复用,又强制子类实现核心逻辑” 的场景。
  • 与接口的区别
    对比维度抽象类接口
    方法类型可包含抽象方法、普通方法、默认方法JDK 8 前仅抽象方法;JDK 8 后支持默认 / 静态方法
    属性类型可包含任意属性(成员变量、常量)仅支持常量(public static final)
    继承 / 实现子类通过extends单继承实现类通过implements多实现
    实例化无法直接实例化无法直接实例化
    核心作用代码复用(提供普通方法)+ 规范方法(抽象方法)纯方法规范(强制实现类遵循标准)
  • 示例
    // 抽象类:图形(提供通用方法,强制子类实现核心方法)
    abstract class Shape {
    // 普通方法(代码复用)
    public void show() {
    System.out.println("这是一个图形");
    }
    // 抽象方法(强制子类实现:计算面积)
    public abstract double calculateArea();
    }
    // 子类1:圆形(继承抽象类,实现抽象方法)
    class Circle extends Shape {
    private double radius; // 半径
    public Circle(double radius) {
    this.radius = radius;
    }
    // 实现抽象方法:计算圆形面积(πr²)
    @Override
    public double calculateArea() {
    return Math.PI * radius * radius;
    }
    }
    // 子类2:矩形(继承抽象类,实现抽象方法)
    class Rectangle extends Shape {
    private double width; // 宽
    private double height; // 高
    public Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
    }
    // 实现抽象方法:计算矩形面积(宽×高)
    @Override
    public double calculateArea() {
    return width * height;
    }
    }
    // 测试抽象类
    public class AbstractClassDemo {
    public static void main(String[] args) {
    Shape circle = new Circle(5);
    circle.show(); // 输出“这是一个图形”
    System.out.println("圆形面积:" + circle.calculateArea()); // 输出≈78.54
    Shape rectangle = new Rectangle(4, 6);
    rectangle.show(); // 输出“这是一个图形”
    System.out.println("矩形面积:" + rectangle.calculateArea()); // 输出24.0
    }
    }

三、核心 API(集合、字符串、日期、工具类)

        集合

  • 定义:用于存储 “动态长度、可灵活操作” 的批量数据,解决数组长度固定的问题,主要分为Collection(单列集合)和Map(双列集合,键值对)两大体系。
  • 核心体系与应用场景
    集合类型具体实现类核心特点应用场景
    Collection → ListArrayList基于数组实现,查询快、增删慢(尾部增删快),线程不安全需频繁查询、少量增删的场景(如商品列表、成绩排名)
    LinkedList基于链表实现,查询慢、增删快,线程不安全需频繁增删、少量查询的场景(如购物车添加 / 删除商品)
    Collection → SetHashSet基于哈希表实现,无序、不可重复,线程不安全去重场景(如用户标签、不重复的 ID 列表)
    TreeSet基于红黑树实现,有序(自然排序 / 自定义排序)、不可重复,线程不安全排序 + 去重场景(如按价格排序的商品 ID)
    MapHashMap基于哈希表实现,无序、键唯一、值可重复,线程不安全键值对映射场景(如用户 ID→用户信息、配置项 key→value)
    TreeMap基于红黑树实现,键有序(自然排序 / 自定义排序),线程不安全有序键值对场景(如按日期排序的日志记录)
  • 示例(ArrayList 与 HashMap)
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    public class CollectionDemo {
    public static void main(String[] args) {
    // 1. ArrayList:存储商品列表
    List products = new ArrayList<>();
    products.add("手机"); // 添加元素
    products.add("电脑");
    products.add("平板");
    System.out.println("商品列表:" + products); // 输出[手机, 电脑, 平板]
    // 遍历ArrayList
    System.out.print("遍历商品:");
    for (String product : products) {
    System.out.print(product + " "); // 输出“手机 电脑 平板 ”
    }
    System.out.println();
    // 2. HashMap:存储用户ID→用户姓名
    Map userMap = new HashMap<>();
    userMap.put(1, "张三"); // 添加键值对
    userMap.put(2, "李四");
    userMap.put(3, "王五");
    System.out.println("用户映射:" + userMap); // 输出{1=张三, 2=李四, 3=王五}
    // 根据键获取值
    String userName = userMap.get(2);
    System.out.println("ID=2的用户:" + userName); // 输出“李四”
    // 遍历HashMap(键值对)
    System.out.print("遍历用户:");
    for (Map.Entry entry : userMap.entrySet()) {
    System.out.print("(" + entry.getKey() + ":" + entry.getValue() + ") ");
    }
    // 输出“(1:张三) (2:李四) (3:王五) ”
    }
    }

        字符串

  • 核心类StringStringBuilderStringBuffer,均用于处理字符串,但特性不同,需根据场景选择。
  • 核心区别与应用场景
    类名可变性线程安全效率应用场景
    String不可变(每次修改生成新对象)安全(无修改操作)低(频繁修改会产生大量临时对象)字符串常量、少量修改的场景(如用户名、固定文本)
    StringBuilder可变(修改自身,不生成新对象)不安全(无同步锁)单线程下频繁修改字符串(如日志拼接、单线程文本处理)
    StringBuffer可变安全(有同步锁)中(锁开销)多线程下频繁修改字符串(如多线程日志记录)
  • 常用方法(String)
    • length():获取字符串长度;
    • charAt(int index):获取指定索引的字符;
    • substring(int beginIndex, int endIndex):截取子串(左闭右开);
    • equals(Object obj):比较字符串内容(区分大小写);
    • contains(CharSequence s):判断是否包含指定子串;
    • replace(CharSequence old, CharSequence new):替换子串。
  • 示例
    public class StringDemo {
    public static void main(String[] args) {
    // 1. String:不可变字符串
    String str = "Hello Java";
    System.out.println("字符串长度:" + str.length()); // 输出10
    System.out.println("第6个字符:" + str.charAt(5)); // 输出'J'(索引从0开始)
    System.out.println("截取子串(0-5):" + str.substring(0, 5)); // 输出"Hello"
    System.out.println("是否包含'Java':" + str.contains("Java")); // 输出true
    // 2. StringBuilder:单线程频繁修改
    StringBuilder sb = new StringBuilder();
    sb.append("Hello"); // 拼接字符串
    sb.append(" ");
    sb.append("World");
    sb.insert(5, " Java"); // 在索引5处插入
    System.out.println("StringBuilder结果:" + sb); // 输出"Hello Java World"
    // 3. StringBuffer:多线程频繁修改(示例略,用法与StringBuilder类似)
    }
    }

        日期

  • 核心类:JDK 8 前用DateCalendar,JDK 8 后推荐用java.time包下的LocalDateTimeLocalDateLocalTime(线程安全、API 更友好),主要用于处理时间的获取、格式化、计算。
  • 核心类与功能
    • LocalDate:处理日期(年、月、日),如2024-05-20
    • LocalTime:处理时间(时、分、秒),如15:30:45
    • LocalDateTime:处理日期 + 时间,如2024-05-20T15:30:45
    • DateTimeFormatter:格式化日期时间(自定义格式,如yyyy-MM-dd HH:mm:ss)。
  • 常用操作
    • 获取当前时间:LocalDateTime.now()
    • 格式化:localDateTime.format(formatter)
    • 时间计算:plusDays(1)(加 1 天)、minusHours(2)(减 2 小时);
    • 解析字符串为日期:LocalDateTime.parse(str, formatter)
  • 示例
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    public class DateDemo {
    public static void main(String[] args) {
    // 1. 获取当前日期时间
    LocalDateTime now = LocalDateTime.now();
    System.out.println("当前时间(默认格式):" + now);
    // 输出如“2024-05-20T15:30:45.123456789”
    // 2. 格式化日期时间(自定义格式)
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String formattedTime = now.format(formatter);
    System.out.println("格式化后时间:" + formattedTime);
    // 输出如“2024-05-20 15:30:45”
    // 3. 时间计算(加1小时、减2天)
    LocalDateTime nextHour = now.plusHours(1);
    LocalDateTime twoDaysAgo = now.minusDays(2);
    System.out.println("1小时后:" + nextHour.format(formatter));
    System.out.println("2天前:" + twoDaysAgo.format(formatter));
    // 4. 解析字符串为LocalDateTime
    String timeStr = "2024-05-18 10:00:00";
    LocalDateTime parsedTime = LocalDateTime.parse(timeStr, formatter);
    System.out.println("解析后的时间:" + parsedTime);
    // 输出“2024-05-18T10:00”
    }
    }

        工具类

  • 定义:Java 提供的java.util包下的工具类,封装了常用的工具方法(如数组操作、集合操作、随机数生成),无需自己实现,直接调用即可。
  • 核心工具类与方法
    工具类核心方法功能描述
    Arrayssort(Object[] a)对数组排序(自然排序 / 自定义排序)
    toString(Object[] a)将数组转换为字符串(便于打印)
    copyOf(Object[] original, int newLength)复制数组(指定新长度)
    binarySearch(Object[] a, Object key)二分查找数组中的元素(需先排序)
    Collectionssort(List<T> list)对 List 排序(自然排序 / 自定义排序)
    max(Collection<? extends T> coll)获取集合中的最大值
    min(Collection<? extends T> coll)获取集合中的最小值
    shuffle(List<?> list)随机打乱 List 中的元素
    synchronizedList(List<T> list)将非线程安全的 List 转为线程安全
  • 示例
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    public class ToolClassDemo {
    public static void main(String[] args) {
    // 1. Arrays工具类:操作数组
    int[] arr = {3, 1, 4, 1, 5, 9};
    Arrays.sort(arr); // 排序数组
    System.out.println("排序后数组:" + Arrays.toString(arr)); // 输出[1, 1, 3, 4, 5, 9]
    int[] copyArr = Arrays.copyOf(arr, 4); // 复制前4个元素
    System.out.println("复制后数组:" + Arrays.toString(copyArr)); // 输出[1, 1, 3, 4]
    int index = Arrays.binarySearch(arr, 4); // 二分查找4的索引
    System.out.println("元素4的索引:" + index); // 输出3
    // 2. Collections工具类:操作集合
    List list = Arrays.asList(3, 1, 4, 1, 5, 9);
    Collections.sort(list); // 排序List
    System.out.println("排序后List:" + list); // 输出[1, 1, 3, 4, 5, 9]
    Integer max = Collections.max(list); // 获取最大值
    Integer min = Collections.min(list); // 获取最小值
    System.out.println("最大值:" + max + ",最小值:" + min); // 输出“最大值:9,最小值:1”
    Collections.shuffle(list); // 随机打乱List
    System.out.println("打乱后List:" + list); // 输出随机顺序(如[3, 5, 1, 9, 4, 1])
    }
    }

四、异常处理与 I/O 基础 

异常处理保障程序稳定性(避免崩溃),I/O 基础实现数据的 “读写操作”(如文件、网络数据),两者是程序与外部交互、应对错误的核心能力。

        异常处理

  • 定义:程序运行过程中出现的 “不正常情况”(如空指针、数组越界、文件不存在),若不处理会导致程序崩溃,通过 “捕获” 或 “抛出” 异常,让程序优雅处理错误。
  • 异常体系
    • 顶层类:Throwable,分为Error(错误,如内存溢出,程序无法处理)和Exception(异常,程序可处理);
    • Exception分为 “编译时异常”(需强制处理,如IOException)和 “运行时异常”(无需强制处理,如NullPointerExceptionArrayIndexOutOfBoundsException)。
  • 核心处理结构
    • try-catch-finallytry包裹可能出错的代码,catch捕获并处理异常,finally无论是否异常都会执行(用于释放资源);
    • throw:手动抛出异常(如参数校验不通过时);
    • throws:声明方法可能抛出的异常(由调用者处理);
    • 自定义异常:继承Exception(编译时异常)或RuntimeException(运行时异常),实现业务专属异常(如 “余额不足异常”)。
  • 示例
    import java.util.Scanner;
    // 自定义异常:余额不足异常
    class InsufficientBalanceException extends Exception {
    public InsufficientBalanceException(String message) {
    super(message); // 调用父类构造方法,传递异常信息
    }
    }
    // 银行账户类:模拟取款
    class BankAccount {
    private double balance;
    public BankAccount(double balance) {
    this.balance = balance;
    }
    // 取款方法:可能抛出自定义异常,用throws声明
    public void withdraw(double amount) throws InsufficientBalanceException {
    if (amount  balance) {
    // 手动抛出自定义异常
    throw new InsufficientBalanceException("余额不足!当前余额:" + balance + ",取款金额:" + amount);
    }
    balance -= amount;
    System.out.println("取款成功!剩余余额:" + balance);
    }
    }
    // 测试异常处理
    public class ExceptionDemo {
    public static void main(String[] args) {
    BankAccount account = new BankAccount(1000);
    Scanner scanner = new Scanner(System.in);
    System.out.print("请输入取款金额:");
    double amount = scanner.nextDouble();
    try {
    account.withdraw(amount); // 可能抛出异常的代码
    } catch (InsufficientBalanceException e) {
    // 捕获自定义异常
    System.out.println("异常信息:" + e.getMessage());
    } catch (IllegalArgumentException e) {
    // 捕获运行时异常
    System.out.println("异常信息:" + e.getMessage());
    } finally {
    // 释放资源(关闭Scanner)
    scanner.close();
    System.out.println("取款操作结束");
    }
    }
    }

        I/O 基础

  • 定义:I/O(Input/Output,输入 / 输出)用于程序与外部设备(如文件、键盘、网络)进行数据交互,核心分为 “字节流”(处理所有文件类型)和 “字符流”(处理文本文件,避免中文乱码)。
  • 核心流体系
    流类型输入流(读数据)输出流(写数据)核心用途
    字节流InputStream(抽象类)→ FileInputStream(文件输入流)OutputStream(抽象类)→ FileOutputStream(文件输出流)读取 / 写入任意文件(如图片、视频、文本)
    字符流Reader(抽象类)→ FileReader(文件字符输入流)→ BufferedReader(缓冲字符输入流)Writer(抽象类)→ FileWriter(文件字符输出流)→ BufferedWriter(缓冲字符输出流)读取 / 写入文本文件(如.txt、.java),缓冲流提升效率
  • 核心操作(文件读写)
    • 写入文件:创建输出流→调用write()方法写入→关闭流(或用try-with-resources自动关闭);
    • 读取文件:创建输入流→调用read()方法读取→关闭流;
    • try-with-resources:JDK 7 + 特性,流对象在try括号中声明,无需手动关闭,程序结束后自动关闭。
  • 示例(字符流读写文本文件)
    import java.io.*;
    public class IODemo {
    public static void main(String[] args) {
    // 1. 写入文本文件(try-with-resources自动关闭流)
    String content = "Hello, Java I/O!这是一段测试文本。";
    try (Writer writer = new FileWriter("test.txt");
    BufferedWriter bufferedWriter = new BufferedWriter(writer)) { // 缓冲流提升效率
    bufferedWriter.write(content);
    bufferedWriter.newLine(); // 换行
    bufferedWriter.write("这是第二行文本。");
    System.out.println("文件写入成功!");
    } catch (IOException e) {
    e.printStackTrace(); // 处理I/O异常
    }
    // 2. 读取文本文件
    try (Reader reader = new FileReader("test.txt");
    BufferedReader bufferedReader = new BufferedReader(reader)) {
    String line; // 存储每行内容
    System.out.println("\n文件内容:");
    while ((line = bufferedReader.readLine()) != null) { // 按行读取(null表示文件结束)
    System.out.println(line);
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

五、Java 内存模型入门 

Java 内存模型(JMM)定义了 Java 虚拟机(JVM)在内存中如何存储数据、如何进行线程间通信,理解 JMM 是后续学习 GC(垃圾回收)、并发编程的基础。

        核心内存分区

JVM 内存分为 5 个区域,各区域功能、线程归属(私有 / 共享)不同,具体如下:

内存区域核心功能线程归属关键特点
程序计数器存储当前线程执行的 “字节码指令地址”(如分支、循环、线程恢复的位置)线程私有内存空间最小,无 OOM(内存溢出)异常
本地方法栈管理 “本地方法”(用native修饰、C/C++ 实现的方法,如System.currentTimeMillis())的调用线程私有可能抛出StackOverflowError(栈溢出)和OutOfMemoryError
Java 虚拟机栈存储线程执行方法时的 “局部变量表”(方法内定义的变量)、“操作数栈”(方法执行时的临时数据)、“动态链接”(方法引用)、“方法出口”(方法返回地址)线程私有1. 局部变量表存储基本数据类型和引用数据类型的地址;2. 栈帧(每个方法对应一个栈帧)随方法调用创建、方法结束销毁;3. 可能抛出StackOverflowError(方法嵌套过深)和OutOfMemoryError
存储 “几乎所有对象实例”(如new User()创建的对象)和数组线程共享1. JVM 内存中最大的区域;2. GC(垃圾回收)的主要区域;3. 可能抛出OutOfMemoryError(对象过多,GC 无法回收)
方法区(JDK 8 + 叫 “元空间”)存储 “已加载的类信息”(类结构、方法信息)、“常量”(如final修饰的常量)、“静态变量”(static修饰的变量)、“即时编译后的代码”线程共享1. JDK 7 及之前叫 “永久代”,JDK 8 后用 “元空间”(基于本地内存,而非 JVM 内存);2. 可能抛出OutOfMemoryError(类加载过多)

        关键概念:线程私有与共享

  • 线程私有:每个线程在创建时会单独分配一份内存,线程间不共享,随线程销毁而释放,包括 “程序计数器”“本地方法栈”“Java 虚拟机栈”;
    • 好处:避免线程间数据干扰,无需同步控制。
  • 线程共享:所有线程共用一份内存,线程间可共享数据,包括 “堆”“方法区”;
    • 好处:实现数据共享(如多个线程操作同一个对象);
    • 问题:可能出现线程安全问题(如多个线程修改同一个对象的属性),需通过锁机制(如synchronized)控制。

        与 GC 的关联

  • GC(垃圾回收):负责回收 “堆” 和 “方法区” 中 “不再被使用的对象”,释放内存,避免内存溢出;
  • 为什么需要 GC
    • 栈内存(虚拟机栈、本地方法栈)的栈帧随方法结束自动销毁,无需 GC;
    • 堆内存的对象由new创建,方法结束后对象可能仍被其他线程或引用指向(如静态变量引用的对象),无法自动销毁,需 GC 判断对象是否 “可达”(是否有引用指向),不可达则回收。
  • 示例理解
    public class MemoryDemo {
    public static void main(String[] args) {
    // 1. user1是局部变量,存储在“Java虚拟机栈”中,指向堆中的User对象
    User user1 = new User("张三", 25);
    // 2. user2是局部变量,也指向堆中的同一个User对象(堆对象被两个引用指向)
    User user2 = user1;
    // 3. user1置为null,不再指向堆对象,但user2仍指向,对象可达,GC不回收
    user1 = null;
    // 4. user2置为null,堆对象无任何引用指向,对象不可达,GC会在合适时机回收
    user2 = null;
    }
    }
posted @ 2025-10-10 08:28  wzzkaifa  阅读(350)  评论(0)    收藏  举报