当前位置: 首页 > news >正文

Java入门首周精要:从基础语法到面向对象核心解析

文章目录

  • Java入门首周精要:从基础语法到面向对象核心解析
    • 1.Java类名与文件名的一致性规则
    • 2.Java和C语言中char类型的区别
    • 3.Java中的注释
    • 4.Java中的‘’+‘’运算符
    • 5.Java的输入输出
    • 6.方法(重载&重写)
      • 方法的重载
      • 方法的重写
    • 7.面向对象(OOP) VS 面向过程(POP)
    • 8.类(Class)和对象(Object)
    • 9.成员变量 VS 局部变量
    • 10.构造方法(构造器)
    • 11.JavaBean是什么?
    • 12.static关键字
    • 13.继承
    • 14.this和super关键字
    • 15.抽象类 VS 接口
    • 16.多态
    • 17.权限修饰符
    • 18.final关键字
    • 19.构造代码块 VS 静态代码块
    • 20.内部类
    • 21.异常
    • 22.为什么String类可以不用new创建对象?
    • 23.增强for

Java入门首周精要:从基础语法到面向对象核心解析

1.Java类名与文件名的一致性规则

规则

  • 如果一个类被声明为 public,那么文件名必须与该类的名称完全一致(包括大小写)
  • 一个 .java 文件中只能有一个 public,但可以有多个非 public 类。
  • 如果没有 public 类,文件名可以任意(但通常与主类名一致)。

Java的设计逻辑

  • Java强制要求 public 类名与文件名一致,是为了让编译器能快速定位类。Java的每个类在编译后都会生成独立的 .class 文件(如 Car.classEngine.class)。
  • public 类可以被其他包中的代码访问,因此需要明确的文件名与类名对应关系,确保JVM在加载类时能找到正确的文件。

建议

  • 始终让文件名与 public 类名一致:避免编译错误。
  • 一个文件只放一个类:提高代码可读性(即使允许放多个类)。
  • 注意大小写:Java区分大小写,Car.javacar.java 是不同的文件!

2.Java和C语言中char类型的区别

C语言

  • C语言中char类型通常为8位(1字节),采用ASCII或本地扩展编码,取值范围通常是 0 − 255 0-255 0255(无符号char)或 − 128 − 127 -128-127 128127(有符号char),符号默认由编译器决定,可显式声明有无符号。
    • 仅能表示256种可能的值,无法直接处理Unicode字符。
    • 多字节字符(如中文)需依赖外部库(如wchar_t或UTF-8编码的函数)。

Java

  • 而Java中的char类型固定为16位(2字节),采用Unicode编码(UTF-16)始终是无符号的,取值范围是\u0000(0)~\uffff(65535)

    • \u 用于表示 Unicode 字符的转义序列,格式为 \uXXXX,其中 XXXX4 位 16 进制数,对应 Unicode 码点的值(C 语言默认不支持 \u 作为字符转义序列,但在 C11 及之后的标准 中,引入了 \u 作为 Unicode 字符转义)。

    • 码点是什么?

      码点(Code Point) 是 Unicode 字符集中的 唯一数字标识符,用来表示一个字符。Unicode 码点的范围是 U+0000U+10FFFF,其中:

      • U+ 表示 Unicode 码点的前缀。
      • 0000 ~ 10FFFF十六进制 数,表示 Unicode 字符的索引。
    • UTF-16编码是一种变长编码,大部分常用字符(BMP平面,即U+0000U+FFFF)用1个char表示。超出BMP的字符(如部分Emoji,U+10000U+10FFFF)需要用2个char(代理对)表示。

      • 什么是BMP?

        BMP,全称为 Basic Multilingual Plane,中文意为基本多文种平面。Unicode 共有17个平面,BMP 是 Unicode 的0号平面,即[U+0000, U+FFFF]区间。BMP 包含了几乎所有的现代语言的文字和大量的符号。

总结

  • C的char
    面向底层,直接操作字节,符号性灵活,适合处理原始数据或ASCII文本,但需手动处理编码和多字节字符。
  • Java的char
    为国际化设计,强制使用UTF-16编码,无符号且类型安全,适合处理多语言文本,但灵活性较低。

3.Java中的注释

单行注释//

多行注释/* ... */

文档注释/** ... */

  • 在Java中,文档注释(Javadoc) 是一种特殊的注释格式,用于生成标准的API文档(HTML格式),方便开发者理解类、方法、字段的功能和使用方式。

  • 语法格式

    /*** 描述内容* @标签名 标签内容*/
    
    • /** 开头,*/ 结尾。
    • 每行以 * 开头(非强制,但建议对齐以增强可读性)。
  • 核心Javadoc标签:

    标签用途示例
    @param描述方法的参数(仅用于方法)@param num1 第一个整数
    @return描述方法的返回值(非void方法必须使用)@return 两个整数的和
    @throws / @exception描述方法可能抛出的异常@throws IllegalArgumentException 参数为负数时抛出
    @deprecated标记方法或类已过时,建议使用替代方案@deprecated 使用 {@link #newMethod()} 代替
    @see添加相关类、方法或资源的参考链接@see java.util.ArrayList
    @since指定引入该功能的版本@since 1.8
    @author标注作者(通常用于类或接口)@author John Doe
    @version指定版本号(通常用于类或接口)@version 1.0.0
    {@link}内联链接到其他类或方法使用 {@link #calculateSum(int, int)} 计算和
    {@code}将内容格式化为代码样式(不解析HTML){@code int x = 5;}
  • 用法示例

    • 类注释

      /*** 表示一个二维坐标系中的点。* * @author Jane Smith* @version 1.2* @since 1.0*/
      public class Point {private int x;private int y;// ...
      }
      
    • 方法注释

      /*** 计算两个整数的和。* * @param num1 第一个加数(必须为非负数)* @param num2 第二个加数* @return 两个参数的和* @throws IllegalArgumentException 如果num1为负数* @see <a href="http://example.com">算法参考文档</a>*/
      public int add(int num1, int num2) {if (num1 < 0) {throw new IllegalArgumentException("num1不能为负数");}return num1 + num2;
      }
      
  • 生成Javadoc文档

    • 命令行生成

      javadoc -d docs -encoding UTF-8 -charset UTF-8 MyClass.java
      
      • -d docs:指定输出目录为docs
      • -encoding UTF-8:指定源文件编码。
      • -charset UTF-8:指定生成文档的字符集。
    • IDE生成

      ToolsGenerate JavaDoc → 配置输出目录和选项 → 点击生成。

  • 核心价值

    生成标准化API文档,提升代码可维护性和团队协作效率。

4.Java中的‘’+‘’运算符

在Java中,+ 运算符是一个多功能操作符,主要用于算术加法字符串连接

  • 算术加法

    • 适用场景:操作数均为数值类型byte, short, int, long, float, double, char)。

    • 规则

      • 若操作数类型不同,会进行隐式类型提升(向更高精度的类型转换)。
      • 运算结果类型与提升后的类型一致。
    • 示例

      int a = 5 + 3;       // 8(int + int → int)
      double b = 5 + 3.0;  // 8.0(int + double → double)
      char c = 'A' + 1;    // 'B'(char提升为int,计算后转回char)
      
  • 字符串拼接

    • 适用场景:任一操作数为字符串String)类型。

    • 规则

      • 非字符串操作数会自动转换为字符串(调用toString()方法)。
      • 运算结果为新的字符串对象。
    • 示例

      String s1 = "Hello" + " World";     // "Hello World"
      String s2 = "Age: " + 25;          // "Age: 25"(int转String)
      String s3 = 10 + 20 + "30";        // "3030"(先计算10+20=30,再连接"30")
      String s4 = "Sum: " + (10 + 20);   // "Sum: 30"(括号改变优先级)
      
    • 在 Java 中,字符串是不可变的,每次使用 + 连接字符串时,实际上是创建了一个新的 String 对象。为了提高性能,Java 提供了 StringBuilderStringBuffer 来优化字符串的连接操作。

      StringBuilder sb = new StringBuilder();
      sb.append("Hello").append(" ").append("World");
      String result = sb.toString(); // "Hello World"
      

5.Java的输入输出

  • 控制台输出

    System.out:标准输出流,默认输出到控制台。

    • System.out.print():输出不换行。
    • System.out.println():输出并换行。
    • System.out.printf():格式化输出(类似C语言)。
    System.out.print("Hello");       // Hello
    System.out.println(" World");    //  World(换行)
    System.out.printf("PI: %.2f", Math.PI); // PI: 3.14
    
  • 控制台输入

    Scanner:最常用的输入工具,可解析基本类型和字符串。

    import java.util.Scanner;    // 导包public class ConsoleInput {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);System.out.print("请输入姓名: ");String name = scanner.nextLine();  // 读取整行输入System.out.print("请输入年龄: ");int age = scanner.nextInt();       // 读取整数System.out.printf("姓名: %s, 年龄: %d", name, age);}
    }
    
    • 常用方法
      • nextInt()nextDouble():读取数值。
      • nextLine():读取整行(包括空格)。
      • next():读取单词(以空格分隔)。

6.方法(重载&重写)

定义

方法是类或对象中用于执行特定任务的代码块。它接受输入参数(可选),执行操作,并可能返回结果。方法封装了功能,提高了代码的可重用性和模块化。

语法

访问修饰符 返回类型 方法名(参数列表) {// 方法体
}
  • 访问修饰符:如 publicprivateprotected,控制方法的可见性。
  • 返回类型:方法返回值的数据类型,无返回值时用 void
  • 参数列表:传递给方法的参数,可为空。
  • 方法体:实现具体逻辑的代码块。

示例

public int add(int a, int b) {return a + b;
}

方法的重载

定义

在同一个类中定义多个同名方法,但它们的参数列表不同(参数类型、个数或顺序不同)。返回类型可以不同,但仅返回类型不同不足以构成重载。

  • 方法名必须相同。
  • 参数列表必须不同(类型、数量或顺序)。
  • 返回类型、访问修饰符和异常声明可以不同。

作用

提高代码可读性,允许用同一方法名处理不同类型或数量的参数。

示例

public class Calculator {// 重载1:两个int参数public int add(int a, int b) {return a + b;}// 重载2:三个int参数public int add(int a, int b, int c) {return a + b + c;}// 重载3:double类型参数public double add(double a, double b) {return a + b;}
}
calc.add(2, 3);      // 调用重载1
calc.add(1, 2, 3);   // 调用重载2
calc.add(1.5, 2.5);  // 调用重载3

方法的重写

定义

子类重新定义父类中已有的方法,以提供特定实现。重写是实现运行时多态的关键。

  • 方法名、参数列表和返回类型必须与父类方法一致(Java 5+ 允许返回子类类型)。
  • 访问修饰符不能比父类更严格(如父类是 protected,子类可为 public,但不能为 private)。
  • 子类方法抛出的异常不能比父类更宽泛。
  • 不能重写 staticfinalprivate 方法。

作用

允许子类自定义行为,实现多态性。

示例

class Animal {public void sound() {System.out.println("动物发出声音");}
}class Dog extends Animal {@Overridepublic void sound() {System.out.println("汪汪");}
}class Cat extends Animal {@Overridepublic void sound() {System.out.println("喵喵");}
}
Animal myDog = new Dog();
myDog.sound(); // 输出 "汪汪"(多态)

@Override 是 Java 中的一个注解(Annotation),用于明确标识某个方法是重写(Override)了父类或接口中的方法。它的核心作用是让编译器帮助你检查方法重写的正确性,避免因拼写错误、参数不匹配等问题导致重写失败。

作用

  • 编译时检查
    如果使用了 @Override 注解,编译器会强制检查该方法是否:

    • 确实重写了父类或接口中的方法。
    • 方法名、参数列表、返回类型与父类完全一致。
    • 访问权限符不低于父类方法(例如,父类方法是 protected,子类不能是 private)。

    如果不符合重写规则,编译器会直接报错,而不是默默接受错误代码。

  • 提高代码可读性
    明确告诉其他开发者这是一个重写方法,增强代码的可维护性。

7.面向对象(OOP) VS 面向过程(POP)

之前学过的C语言是典型的面向过程编程语言,而现在正在学的Java面向对象编程语言的代表。

什么是面向过程编程?

  • 定义

    面向过程编程是一种以**过程(函数)**为核心的编程范式,通过将程序分解为一系列线性步骤(函数调用),逐步操作数据以完成任务。其核心思想是“怎么做”(How to do)。

  • 核心特征

    • 函数为中心:程序由函数构成,每个函数实现特定功能。
    • 数据与行为分离:数据(变量)独立于函数,函数通过参数接收数据并处理。
    • 线性流程:代码按预定义顺序执行,强调算法和逻辑步骤。
    • 典型语言:C、Pascal、Fortran。
  • 优缺点

    优点缺点
    简单直观,适合小型程序代码复用性差
    执行效率高难以管理复杂系统
    适合算法密集型任务数据与行为分离易导致耦合度高

什么是面向对象编程?

  • 定义

    面向对象编程是一种以对象为核心的编程范式,将现实世界的实体抽象为包含数据(属性)和行为(方法)的对象,并通过封装、继承、多态、抽象四大特性构建程序。其核心思想是“谁来做”(Who does what)。

  • 核心特征

    • 对象为中心:程序由对象组成,对象是类的实例。
    • 封装性:将数据和方法绑定,隐藏内部实现细节。
    • 继承性:子类复用父类的属性和方法。
    • 多态性:同一接口在不同对象中有不同实现。
    • 典型语言:Java、C++、Python。
  • 优缺点

    优点缺点
    代码模块化,易维护扩展学习曲线陡峭
    支持代码复用(继承/组合)性能略低于面向过程
    适合复杂系统开发过度设计可能导致冗余

核心对比

面向过程面向对象
核心单位函数对象
设计目标步骤分解职责划分
数据与行为分离绑定(封装)
扩展性低(需修改函数)高(继承、多态)
适用场景小型工具、算法、嵌入式开发大型系统、GUI、企业级应用

叽里咕噜的说什么呢,想象你要做一道菜(比如番茄炒蛋),面向过程就是:你亲自动手,严格按照步骤一步一步来:

1. 洗番茄 → 2. 切番茄 → 3. 打鸡蛋 → 4. 开火 → 5. 炒菜 → 6. 出锅

关注的是步骤(先干什么,后干什么),所有事情都要自己干,没有分工,假如你还要做另一道菜(比如青椒肉丝),你需要重写一遍所有步骤。

想象你开了一家餐厅,面向对象就是:你把任务分给不同的人(对象),比如:

- 厨师对象:负责做菜  
- 服务员对象:负责端菜  
- 收银员对象:负责收钱

关注的是谁来做(每个对象只负责自己的任务),不同对象之间互相配合(比如服务员告诉厨师做菜),如果要新增一道菜,只需要让厨师学新菜谱,其他岗位不用变。

  • 面向过程“自己做所有事”(关注步骤)。
  • 面向对象“让别人帮你做事”(关注分工)。

为什么要有面向对象?

想象你开的是大型连锁餐厅

  • 如果每道菜都自己从头做到尾(面向过程),会累死,而且难以管理。
  • 如果用面向对象的方式,每个岗位各司其职,系统更灵活,容易扩展(比如新增一个配送员送外卖)。

8.类(Class)和对象(Object)

类(Class)

  • 定义

    • 是一个模板或蓝图,用于描述一类对象的属性(成员变量)行为(成员方法)
    • 类定义了对象的类型,但本身不占用内存空间,只有通过 new 关键字创建对象时才会分配内存。
  • 语法

    public class 类名 {// 成员变量(属性)数据类型 变量名;// 构造方法(初始化对象)public 类名(参数列表) {// 初始化代码}// 普通方法(行为)返回类型 方法名(参数列表) {// 方法体}
    }
    
  • 示例

    public class Car {// 成员变量(属性)String color;String brand;// 构造方法public Car(String color, String brand) {this.color = color;this.brand = brand;}// 方法(行为)public void start() {System.out.println(brand + "汽车启动了!");}
    }
    

对象(Object)

  • 定义

    • 对象 是类的一个具体实例,通过 new 关键字创建。
    • 每个对象在内存中独立存在,拥有自己的成员变量值(数据)和方法实现(行为)。
  • 如何创建对象?

    • 使用 new 关键字:

      • 分配内存:在堆内存中为对象分配空间。
      • 调用构造方法:初始化对象的成员变量。
      • 返回引用:将对象的内存地址赋给变量(引用)。
    • 语法

      类名 对象名 = new 类名(参数列表);
      
    • 示例

      public class Main {public static void main(String[] args) {// 创建 Car 类的对象Car myCar = new Car("红色", "Toyota");Car yourCar = new Car("蓝色", "BMW");// 调用对象的方法myCar.start(); // 输出:Toyota汽车启动了!yourCar.start(); // 输出:BMW汽车启动了!}
      }
      

9.成员变量 VS 局部变量

成员变量

  • 定义

    • 定义在类内部,但在方法、构造方法或代码块之外
    • 包括两种类型:
      • 实例变量(非静态成员变量)
      • 类变量(静态成员变量,用 static 修饰)
  • 特点

    • 作用域
      • 整个类内部均可访问。
      • 实例变量通过对象访问(obj.variable),静态变量通过类名访问(Class.variable)。
    • 生命周期
      • 实例变量:随对象创建而存在,对象被垃圾回收时销毁。
      • 静态变量:随类加载而存在,程序结束时销毁。
    • 默认值
      • 成员变量有默认初始值(如 int 默认为 0,对象类型默认为 null)。
    • 存储位置
      • 实例变量:存储在堆内存(对象内部)。
      • 静态变量:存储在方法区(类元数据区)。
  • 示例

    public class Car {// 实例变量(成员变量)private String brand;  // 默认值为 nullprivate int speed;     // 默认值为 0// 静态变量(类变量)public static int wheels = 4;  // 显式初始化public void accelerate() {speed += 10;  // 可以直接访问成员变量}
    }
    

局部变量

  • 定义

    定义在方法、构造方法、代码块内部形参列表中。

  • 特点

    • 作用域
      • 仅在定义它的方法、代码块内部有效。
      • 超出作用域后无法访问。
    • 生命周期
      • 随方法/代码块的执行而创建,执行结束后销毁。
    • 默认值
      • 没有默认值,必须显式初始化后才能使用。
    • 存储位置
      • 存储在栈内存(方法调用栈帧中)。
  • 示例

    public class Calculator {public int add(int a, int b) {  // 形参 a、b 是局部变量int result = a + b;         // 局部变量 resultreturn result;              // result 的作用域仅在 add 方法内}public void printSum() {int x = 5;                 // 局部变量 xint y = 10;System.out.println(x + y);  // 正确System.out.println(result); // 错误!result 在此不可见}
    }
    

核心对比

特性成员变量局部变量
定义位置类内部,方法外方法、代码块内部或形参列表
作用域整个类内部仅方法/代码块内部
生命周期对象或类存在期间方法/代码块执行期间
默认值有默认值(如 0/null必须显式初始化
存储位置堆(实例变量)或方法区(静态)
访问权限可添加访问修饰符(如 public不能使用访问修饰符
内存分配自动分配需要手动初始化

局部变量和成员变量同名时怎么办?

局部变量会覆盖成员变量(就近原则),通过 this 关键字访问成员变量。

public class Test {private int value = 10;public void setValue(int value) {this.value = value;  // this.value 是成员变量,value 是局部变量}
}

10.构造方法(构造器)

在 Java 中,构造方法(Constructor)是类中用于初始化对象的特殊方法,在对象创建时自动调用。

核心特性

  • 命名与类名相同
    构造方法必须与类名完全一致(包括大小写)。

  • 无返回类型
    构造方法没有返回值(连 void 也不写),例如:

    public class Student {// 构造方法(无返回类型)public Student() { ... }
    }
    
  • 自动触发
    通过 new 关键字创建对象时,构造方法自动执行。

  • 可重载
    一个类可以有多个构造方法(参数不同),提供多种初始化方式。

分类

  • 默认构造方法(无参构造方法)

    • 如果类中未显式定义任何构造方法,Java 编译器会自动生成一个默认的无参构造方法

    • 示例:

      public class Student {// 编译器自动生成默认构造方法:public Student() {}
      }
      
  • 自定义构造方法(带参数)

    • 开发者显式定义,用于灵活初始化对象属性。

    • 示例:

      public class Student {private String name;private int age;// 自定义构造方法public Student(String name, int age) {this.name = name;this.age = age;}
      }
      

基本用法

public class Student {private String name;private int age;// 无参构造方法(显式定义)public Student() {}// 有参构造方法public Student(String name, int age) {this.name = name;this.age = age;}public static void main(String[] args) {Student stu1 = new Student();            // 调用无参构造方法Student stu2 = new Student("张三", 18);  // 调用有参构造方法}
}

构造方法的重载

public class Car {private String brand;private String color;// 构造方法1:仅初始化品牌public Car(String brand) {this.brand = brand;this.color = "黑色";}// 构造方法2:初始化品牌和颜色public Car(String brand, String color) {this.brand = brand;this.color = color;}
}

构造方法(构造器) 是对象创建的入口,用于确保对象初始状态合法。通过重载构造方法,可以提供多种初始化方式。

11.JavaBean是什么?

定义JavaBean 是一种符合特定编码规范的 Java 类,主要用于封装数据提供标准化操作

核心规范

  • 公共的无参构造方法

    • 类必须提供无参数构造方法,以便通过反射机制实例化对象。

    • 示例:

      public class User {public User() {} // 必须有无参构造方法
      }
      
  • 属性私有化

    • 所有属性(字段)必须声明为 private,禁止直接暴露给外部。

      private String name;
      private int age;
      
  • 通过公共方法访问属性

    • 提供 getXxx()setXxx() 方法操作属性(称为 Getter 和 Setter)。

    • 布尔类型属性可使用 isXxx() 作为 Getter。

      public String getName() {return name;
      }
      public void setName(String name) {this.name = name;
      }
      

示例

public class User {// 属性私有化private String name;private int age;private boolean active;// 无参构造方法(必须)public User() {}// 带参构造方法(可选)public User(String name, int age) {this.name = name;this.age = age;}// Getter 和 Setter(必须)public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 布尔类型可使用 isXxx()public boolean isActive() {return active;}public void setActive(boolean active) {this.active = active;}
}

12.static关键字

static 是 Java 中用于修饰类成员(变量、方法、代码块、内部类)的关键字,表示该成员属于类本身而非类的实例。其主要目的是实现与类直接关联的功能或数据共享,避免重复创建实例的消耗。

应用场景

  • 静态变量(类变量)

    • 定义:用 static 修饰的成员变量,属于类而非实例。

    • 特点

      • 所有实例共享同一份静态变量。
      • 内存中仅在类加载时分配一次(存储在方法区/元空间)。
      • 可通过 类名.变量名 直接访问,无需实例化对象。
    • 示例

      public class Counter {static int count = 0;  // 静态变量public Counter() {count++;  // 所有实例共享 count}public static void main(String[] args) {new Counter();new Counter();System.out.println(Counter.count); // 输出 2}
      }
      
  • 静态方法

    • 定义:用 static 修饰的方法,属于类而非实例。

    • 特点

      • 只能直接访问静态成员(变量/方法),不能访问实例成员。
      • 可通过 类名.方法名() 直接调用。
      • 常用作工具方法(如 Math.sqrt())。
    • 示例

      public class MathUtils {public static int add(int a, int b) { // 静态方法return a + b;}public static void main(String[] args) {int result = MathUtils.add(3, 5); // 直接调用System.out.println(result); // 输出 8}
      }
      
  • 静态代码块

    • 定义:用 static { ... } 定义的代码块,在类加载时执行一次。

    • 用途

      • 初始化静态变量。
      • 加载静态资源(如配置文件)。
    • 示例

      public class DatabaseConfig {static String url;static String username;static {  // 静态代码块url = "jdbc:mysql://localhost:3306/mydb";username = "root";System.out.println("数据库配置已加载");}
      }
      
  • 静态内部类

    • 定义:用 static 修饰的内部类,不依赖外部类实例。

    • 特点

      • 可直接创建实例:new Outer.Inner()
      • 不能访问外部类的非静态成员。
      • 常用于工具类或单例模式。
    • 示例

      public class Outer {static class Inner {  // 静态内部类void print() {System.out.println("静态内部类");}}public static void main(String[] args) {Outer.Inner inner = new Outer.Inner();  // 直接创建inner.print();}
      }
      

底层原理

  • 内存分配
    • 静态变量存储在方法区(Method Area)(Java 8 后为元空间 MetaSpace)。
    • 类加载时初始化,生命周期与类相同。
  • 类加载机制
    • JVM 首次使用类时加载类信息,静态代码块和静态变量在此阶段初始化。
    • 类卸载时静态资源才会释放(通常由 JVM 管理)。

注意事项

场景规则
访问权限静态方法只能访问静态成员,非静态方法可访问静态和非静态成员。
多线程安全静态变量是共享资源,需通过同步机制(如 synchronized)保证线程安全。
继承与重写静态方法不能被子类重写(但可以隐藏),且不支持 @Override
设计模式过度使用 static 会导致代码耦合度高,违反面向对象设计原则。

为什么静态方法不能访问非静态成员?

非静态成员依赖对象实例存在,而静态方法在类加载时即可调用,此时对象可能尚未创建。

静态变量与实例变量的区别?

维度静态变量实例变量
归属对象实例
内存分配类加载时分配(方法区)对象创建时分配(堆内存)
生命周期与类共存亡与对象共存亡

13.继承

定义

继承 是面向对象编程(OOP)的三大特性之一(封装、继承、多态),允许一个类(子类/派生类)基于另一个类(父类/基类)构建,复用父类的属性和方法,并可以扩展或修改其功能。

核心作用

  • 代码复用:避免重复编写公共代码。
  • 层次化设计:建立类之间的层次关系(如动物 → 猫 → 布偶猫)。
  • 多态支持:通过父类引用操作子类对象。

语法:使用 extends 关键字实现继承

class 父类 {// 父类属性和方法
}class 子类 extends 父类 {// 子类特有的属性和方法
}

继承的成员范围

  • 子类可继承的成员
    • publicprotected 修饰的属性和方法。
    • 默认访问权限(无修饰符)的成员(若子类与父类在同一包中)。
  • 不可继承
    • private 成员。
    • 父类的构造方法(但可通过 super() 调用)。

子类可重写父类的方法,以提供特定实现。

class Animal {public void makeSound() {System.out.println("动物发出声音");}
}class Cat extends Animal {@Overridepublic void makeSound() {System.out.println("喵喵");}
}

构造方法与继承

  • 创建子类对象时,父类构造方法优先执行。

    class Parent {Parent() {System.out.println("父类构造方法");}
    }class Child extends Parent {Child() {super(); // 默认隐含调用父类无参构造System.out.println("子类构造方法");}
    }// 输出:
    // 父类构造方法
    // 子类构造方法
    
  • 若父类只有带参构造方法,子类必须显式调用 super(参数)

    class Parent {Parent(int value) { ... }
    }class Child extends Parent {Child() {super(10); // 必须显式调用}
    }
    

单继承与多继承

Java只支持单继承(一个子类只能有一个直接父类),但可以通过接口(implements)实现多继承的效果

14.this和super关键字

this关键字

  • 作用

    • 指向当前对象的引用,用于在类的内部访问当前对象的成员(属性、方法、构造方法)。
    • 主要解决变量名冲突(如局部变量与成员变量同名)。
  • 使用场景

    • 区分成员变量和局部变量

      public class Person {private String name;  // 成员变量public void setName(String name) {  // 参数(局部变量)this.name = name;  // 用 this 区分同名变量}
      }
      
    • 调用当前对象的其他构造方法(必须在构造方法的第一行使用)

      public class Person {private String name;private int age;// 无参构造方法调用有参构造方法public Person() {this("Unknown", 0);  // 调用下面的构造方法}public Person(String name, int age) {this.name = name;this.age = age;}
      }
      
    • 返回当前对象本身

      public class Counter {private int count;public Counter increment() {count++;return this;  // 返回当前对象,支持链式调用}
      }// 使用示例
      Counter counter = new Counter().increment().increment();
      
  • 注意事项

    • 不能用于静态方法static 方法属于类,不依赖对象)。
    • 不能单独使用(必须指向具体的成员)。

super关键字

  • 作用

    • 指向父类对象的引用,用于在子类中访问父类的成员(属性、方法、构造方法)。
    • 主要解决继承中的成员覆盖问题
  • 使用场景

    • 调用父类的构造方法

      • 必须在子类构造方法的第一行使用。

      • 如果父类没有无参构造方法,必须显式调用 super(...)

        class Animal {private String type;public Animal(String type) {this.type = type;}
        }class Dog extends Animal {public Dog() {super("犬科");  // 显式调用父类有参构造方法}
        }
        
    • 访问父类的成员变量或方法

      • 当子类覆盖父类方法时,用 super 调用父类原始方法。

        class Animal {public void eat() {System.out.println("动物在吃东西");}
        }class Dog extends Animal {@Overridepublic void eat() {super.eat();  // 先调用父类的 eat()System.out.println("狗在啃骨头");}
        }
        
    • 访问父类被隐藏的成员变量

      class Parent {String name = "Parent";
      }class Child extends Parent {String name = "Child";public void printNames() {System.out.println(super.name);  // 输出 ParentSystem.out.println(this.name);   // 输出 Child}
      }
      
  • 注意事项

    • 不能用于静态上下文(静态方法或静态块)。
    • 不能单独使用(必须指向具体的父类成员)。

注意

  • 在构造方法中,this()super() 不能共存,必须放在第一行且只能调用一次。
  • super 只能直接访问直接父类,无法跨级访问祖父类。

示例

class Vehicle {String type;public Vehicle(String type) {this.type = type;}public void start() {System.out.println(type + "启动");}
}class Car extends Vehicle {String brand;public Car(String brand) {super("汽车");  // 调用父类构造方法this.brand = brand;}@Overridepublic void start() {super.start();  // 调用父类的 start()System.out.println(brand + "汽车正在行驶");}
}public class Main {public static void main(String[] args) {Car car = new Car("丰田");car.start();}
}// 输出:
// 汽车启动
// 丰田汽车正在行驶

15.抽象类 VS 接口

什么是抽象?

抽象(Abstraction)是面向对象编程的核心思想之一,指提取对象的本质特征,忽略具体实现细节。通过抽象,可以定义统一的规范或模板,让具体实现由子类或实现类完成。

抽象类(Abstract Class)

  • 定义:用 abstract 修饰的类,称为抽象类。它可以包含抽象方法(无具体实现)和具体方法(有实现),用于定义部分实现的模板

  • 核心特性

    • 不能被实例化:只能通过子类继承后使用。
    • 可以包含抽象方法:用 abstract 修饰的方法,无方法体。
    • 可以包含具体方法:普通方法的实现。
    • 可以定义成员变量:与普通类相同。
    • 可以有构造方法:用于子类初始化。
  • 示例

    public abstract class Animal {// 抽象方法(无实现)public abstract void makeSound();// 具体方法(有实现)public void eat() {System.out.println("动物进食");}
    }
    
  • 使用场景:

    • 定义模板方法模式:父类定义算法骨架,子类实现具体步骤。
    • 部分方法需复用:抽象类中既有通用实现,又预留扩展点。
    • 需要状态管理:抽象类可定义成员变量保存状态。

接口(Interface)

  • 定义:用 interface 定义的类型,用于描述对象的行为规范。接口中的方法默认是抽象的(Java 8 前),支持多继承。

  • 核心特性

    • 默认方法(Default Method):用 default 修饰,提供默认实现。
    • 静态方法(Static Method):用 static 修饰,直接通过接口调用。
    • 私有方法(Java 9+):用 private 修饰,辅助默认方法。
    • 成员变量默认是 public static final:即常量。
    • 不能定义构造方法:无法实例化。
  • 示例

    public interface Flyable {// 抽象方法(默认 public abstract)void fly();// 默认方法(Java 8+)default void glide() {System.out.println("滑翔中");}// 静态方法(Java 8+)static int getMaxSpeed() {return 1000;}
    }
    
  • 使用场景

    • 定义行为规范:如 Runnable 接口定义线程任务。
    • 实现多继承:一个类可实现多个接口。
    • 解耦组件:通过接口隔离实现与调用方。

对比

维度抽象类(Abstract Class)接口(Interface)
关键字abstract classinterface
实例化不能直接实例化不能直接实例化
成员变量普通变量(可非 final)默认 public static final(常量)
构造方法可以有不能有
继承关系单继承(一个子类只能继承一个抽象类)多继承(一个类可实现多个接口)
设计目的代码复用,定义部分实现定义行为规范,解耦设计

如何选择

  • 优先使用接口:避免继承带来的强耦合。
  • 抽象类用于代码复用:当多个类有共同逻辑时。

16.多态

定义多态(Polymorphism) 是面向对象编程(OOP)的核心特性之一,指同一操作作用于不同对象时,可以有不同的行为。它允许使用统一的接口处理不同类型的对象,从而提高代码的灵活性和可扩展性。

Java 中的多态分为两类:

类型实现方式特点
编译时多态方法重载(Overloading)根据参数列表在编译时确定调用的方法。
运行时多态方法重写(Overriding) + 继承根据对象实际类型在运行时确定调用的方法。

运行时多态(动态绑定)

  • 核心机制:JVM 在运行时根据对象的实际类型(而非引用类型)动态绑定要执行的方法。

  • 条件

    • 继承关系:存在父类与子类。
    • 方法重写:子类重写父类的方法。
    • 向上转型:父类引用指向子类对象。
  • 示例

    class Animal {public void sound() {System.out.println("动物发出声音");}
    }class Dog extends Animal {@Overridepublic void sound() {System.out.println("汪汪");}
    }class Cat extends Animal {@Overridepublic void sound() {System.out.println("喵喵");}
    }public class Main {public static void main(String[] args) {Animal a1 = new Dog();  // 向上转型Animal a2 = new Cat();a1.sound();  // 输出 "汪汪"(动态绑定)a2.sound();  // 输出 "喵喵"}
    }
    

应用场景

  • 统一接口处理不同对象。
  • 结合工厂模式,通过多态创建不同子类对象。

多态与类型转换

  • 向上转型

    • 子类对象赋值给父类引用(自动完成)。

    • 特点:安全,但只能访问父类声明的方法。

      Animal animal = new Dog();  // 向上转型
      
  • 向下转型

    • 父类引用强制转换为子类类型(需显式转换)。

    • 风险:可能抛出 ClassCastException

    • 安全做法:使用 instanceof 检查。

      if (animal instanceof Dog) {Dog dog = (Dog) animal;  // 安全向下转型dog.bark();
      }
      

注意事项

  • 静态方法不支持重写,无多态性(通过类名调用)。
  • 私有方法不可被重写,无多态性。
  • final 方法禁止重写,无多态性。
  • 成员变量无多态性,访问时取决于引用类型。
  • 构造方法不可被重写,无多态性。

17.权限修饰符

权限修饰符总览

修饰符类内部同包内子类(不同包)其他包
public
protected
默认(不写)
private

  • 默认权限:不使用任何修饰符,称为包级私有(package-private)。
  • 子类权限protected 允许不同包的子类访问父类成员。
  • 类本身的修饰符:外部类只能使用 public 或默认权限(不能是 protectedprivate)。

public(公开)

  • 作用范围:任何地方均可访问。

  • 典型场景

    • 开放给外部调用的方法(如工具类方法)。
    • 常量(public static final)。
    • 主类(包含 main 方法的类必须用 public)。
  • 示例

    public class Calculator {public static final double PI = 3.14159;  // 公开常量public int add(int a, int b) {  // 公开方法return a + b;}
    }
    

protected(受保护)

  • 作用范围:本类、同包类、不同包的子类。

  • 典型场景

    • 父类中希望被子类继承或重写的方法或属性。
    • 框架设计中需要被子类扩展的成员。
  • 示例

    public class Animal {protected void breathe() {  // 子类可继承并调用System.out.println("呼吸");}
    }class Dog extends Animal {public void showBreathe() {breathe();  // 子类可直接调用父类的 protected 方法}
    }
    

默认权限(包级私有)

  • 作用范围:本类、同包类。

  • 典型场景

    • 内部工具方法或属性,不希望被其他包访问。
    • 模块化设计中,包内协作的类。
  • 示例

    class Logger {  // 默认权限,只能在同包内使用void log(String message) {  // 默认权限方法System.out.println("[LOG] " + message);}
    }
    

private(私有)

  • 作用范围:仅本类内部。

  • 典型场景

    • 隐藏类的内部实现细节(如成员变量)。
    • 防止外部直接修改数据,通过公共方法(getter/setter)控制访问。
  • 示例

    public class BankAccount {private double balance;  // 私有属性,外部无法直接访问public void deposit(double amount) {  // 公开方法控制存取if (amount > 0) {balance += amount;}}public double getBalance() {  // 提供公共读取接口return balance;}
    }
    

注意事项

  • 类的修饰符
    • 外部类只能使用 public 或默认权限。
    • 内部类可以是 privateprotected
  • 方法重写时的权限
    • 子类重写父类方法时,权限不能缩小(如父类方法是 public,子类不能改为 protected)。
  • 构造方法的权限
    • 构造方法可以是任意权限(如 private 用于单例模式)。

建议

  • 最小化访问原则
    • 优先使用最严格的权限(如 private),仅在必要时放宽。
    • 减少代码耦合,提高安全性。
  • 封装数据
    • 成员变量尽量设为 private,通过公共方法(getter/setter)控制访问。
    • 避免直接暴露内部状态。
  • 模块化设计
    • 使用默认权限隐藏包内实现细节。
    • 通过 public 类或方法对外提供接口。

18.final关键字

定义final 是 Java 中用于限制类、方法或变量的修改或继承的关键字,其核心目标是增强代码的安全性、不可变性和设计约束

作用

修饰对象作用
变量变量值(或引用)不可变(常量)。
方法方法不能被子类重写。
类不能被继承。
  • 修饰变量

    • 基本数据类型变量

      • 变量值一旦初始化,不可修改。

        final int MAX_VALUE = 100;
        // MAX_VALUE = 200;  // 编译错误:无法为final变量赋值
        
    • 引用类型变量

      • 引用不可变(即不能指向其他对象),但对象内部状态可修改。

        final List<String> list = new ArrayList<>();
        list.add("Java");   // 允许:修改对象内容
        // list = new LinkedList<>(); // 编译错误:不能改变引用
        
    • 成员变量与局部变量

      • 成员变量:必须显式初始化(可在声明时、构造方法或初始化块中赋值)。

      • 局部变量:只需在使用前初始化一次。

        class Example {final int a = 10;        // 声明时初始化final int b;Example() {b = 20;              // 构造方法中初始化}
        }
        
  • 修饰方法

    • 禁止子类重写

      • 确保父类方法逻辑不被修改。

        class Parent {public final void show() {System.out.println("父类方法");}
        }class Child extends Parent {// 编译错误:无法重写final方法// public void show() { ... }
        }
        
    • private 的隐式 final

      • 若方法为 private,则隐式具有 final 效果(子类无法访问,更无法重写)。

        class Parent {private void method() {} // 隐式final
        }class Child extends Parent {// 合法:实际是子类的新方法,非重写private void method() {}
        }
        
  • 修饰类

    • 禁止继承

      • 保证类不可被扩展(如 StringInteger 等核心类均为 final)。

        final class ImmutableClass { ... }// 编译错误:无法继承final类
        // class SubClass extends ImmutableClass { ... }
        
    • 设计不可变类

      • 若类为 final,且所有字段为 final,则对象创建后状态不可变。

        public final class ImmutablePoint {private final int x;private final int y;public ImmutablePoint(int x, int y) {this.x = x;this.y = y;}// 仅提供getter,无setter
        }
        

19.构造代码块 VS 静态代码块

在 Java 中,代码块(Code Block)是一段被大括号 {} 包围的代码,用于控制变量的作用域或定义代码的执行逻辑。

实例代码块(构造代码块)

  • 定义:直接写在类中,无修饰符,每次创建对象时执行(在构造方法之前)。

  • 作用:初始化实例变量或执行对象共有的初始化逻辑。

  • 语法

    {// 初始化实例变量或通用逻辑
    }
    
  • 示例

    public class Car {String brand;int speed;// 实例代码块:每次 new 对象时执行{speed = 0;  // 所有 Car 对象初始速度为 0System.out.println("实例代码块执行:车辆已启动");}public Car(String brand) {this.brand = brand;}
    }
    

静态代码块

  • 定义:用 static 修饰,属于类级别,在类加载时执行一次

  • 作用:初始化静态变量或加载静态资源(如配置文件)。

  • 语法

    static {// 初始化静态资源
    }
    
  • 示例

    public class DatabaseConfig {static String url;static String username;// 静态代码块:类加载时读取配置static {url = "jdbc:mysql://localhost:3306/mydb";username = "admin";System.out.println("静态代码块执行:数据库配置已加载");}
    }
    

实例代码块 vs 静态代码块

  • 实例代码块:每次 new 对象时执行(在构造方法之前)。
  • 静态代码块:类加载时执行一次(仅一次)。

示例

public class ExecutionOrder {static {System.out.println("静态代码块执行");}{System.out.println("实例代码块执行");}public ExecutionOrder() {System.out.println("构造方法执行");}public static void main(String[] args) {new ExecutionOrder();new ExecutionOrder();}
}// 输出:
// 静态代码块执行
// 实例代码块执行
// 构造方法执行
// 实例代码块执行
// 构造方法执行

使用场景与建议

  • 实例代码块
    • 场景:多个构造方法共有的初始化逻辑(如设置默认值)。
    • 建议:可将通用逻辑提取到私有方法中,由构造方法调用。
  • 静态代码块
    • 场景:初始化全局配置(如数据库连接)、加载静态资源(如图片、文件)。
    • 建议:避免在静态代码块中执行耗时操作(影响类加载速度)。

总结

  • 静态代码块处理类级初始化,实例代码块处理对象级初始化。
  • 优先选择构造方法或方法封装逻辑,避免滥用代码块!

20.内部类

在 Java 中,内部类(Inner Class) 是定义在另一个类内部的类,它可以访问外部类的成员,并实现更灵活的代码封装。

成员内部类

  • 定义:直接定义在外部类的成员位置(与属性、方法同级)。

  • 特点

    • 可以访问外部类的所有成员(包括 private)。
    • 依赖外部类实例存在(不能有静态成员,除非用 static final 常量)。
  • 示例

    public class Outer {private int outerField = 10;// 成员内部类class Inner {void print() {System.out.println("访问外部类字段:" + outerField);  // 直接访问外部类成员}}
    }
    
    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();  // 必须通过外部类实例创建
    

静态内部类

  • 定义:用 static 修饰的内部类。

  • 特点

    • 不依赖外部类实例(可直接创建)。
    • 不能直接访问外部类的非静态成员(只能访问静态成员)。
  • 示例

    public class Outer {private static int staticField = 20;private int instanceField = 30;static class StaticInner {void print() {System.out.println(staticField);  // 合法// System.out.println(instanceField);  // 错误!无法访问非静态成员}}
    }
    
    Outer.StaticInner inner = new Outer.StaticInner();  // 直接创建
    

局部内部类

  • 定义:定义在方法或代码块内部的类。

  • 特点

    • 作用域仅限于所在方法或代码块。
    • 可以访问外部类的成员,但只能访问所在方法的 final 或 effectively final 局部变量
  • 示例

    public class Outer {private int outerField = 40;public void method() {int localVar = 50;  // 必须为 final 或 effectively finalclass LocalInner {void print() {System.out.println(outerField);  // 合法System.out.println(localVar);   // 合法(localVar 不可修改)}}LocalInner inner = new LocalInner();inner.print();}
    }
    

匿名内部类

  • 定义:没有名字的局部内部类,通常用于简化代码(如事件监听、线程实现)。

  • 特点

    • 直接继承父类或实现接口。
    • 只能使用一次(无法复用)。
  • 示例

    public interface ClickListener {void onClick();
    }public class Button {public void setOnClickListener(ClickListener listener) {listener.onClick();}
    }// 使用匿名内部类
    Button button = new Button();
    button.setOnClickListener(new ClickListener() {@Overridepublic void onClick() {System.out.println("按钮被点击!");}
    });
    

应用场景

  • 封装性增强

    • 场景:将仅用于某个外部类的辅助逻辑封装在内部(如链表节点 Node)。

      public class LinkedList {private Node head;// 成员内部类:外部无需关心 Node 的实现private class Node {int data;Node next;}
      }
      
  • 回调与事件处理

    • 场景:匿名内部类简化事件监听(如 Android 点击事件)。

      // Java Swing 示例
      JButton button = new JButton("提交");
      button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("提交表单");}
      });
      
  • 访问外部类私有成员

    • 场景:内部类直接操作外部类私有属性。

      public class Outer {private int secret = 100;class Inner {void revealSecret() {System.out.println("秘密是:" + secret);  // 直接访问 private 成员}}
      }
      
  • 静态工具类

    • 场景:静态内部类实现与外部类相关的工具逻辑。

      public class MathUtils {// 静态内部类:提供特定算法public static class Calculator {public static int add(int a, int b) {return a + b;}}
      }// 使用
      int sum = MathUtils.Calculator.add(2, 3);
      

内部类是实现高内聚、低耦合的重要手段,但需根据场景选择合适类型,避免滥用!

21.异常

定义异常(Exception) 是程序执行过程中发生的非正常事件,它会中断程序的正常流程。Java 通过异常机制提供了一种结构化的错误处理方式。

分类

Java 异常类均继承自 Throwable,分为三大类:

类型特点示例
ErrorJVM 严重错误,程序无法恢复(通常不处理)OutOfMemoryError
检查型异常(Checked Exception)编译时强制要求处理(继承自 Exception 但非 RuntimeException 的子类)IOException, SQLException
非检查型异常(Unchecked Exception)运行时异常,通常由程序逻辑错误引起(RuntimeException 及其子类)NullPointerException, ArrayIndexOutOfBoundsException

异常处理

  • 使用try-catch-finally块捕获并处理异常

    • 核心思想:在代码中直接捕获异常并处理,避免程序终止。

    • 适用场景:当前方法明确知道如何处理异常时(如重试、回滚、日志记录等)。

    • 语法

      try {// 可能抛出异常的代码
      } catch (ExceptionType1 e1) {// 处理特定异常
      } catch (ExceptionType2 e2) {// 处理其他异常
      } finally {// 无论是否异常,最终执行的代码(如释放资源)
      }
      
    • 示例

      try {FileInputStream fis = new FileInputStream("file.txt");
      } catch (FileNotFoundException e) {System.out.println("文件未找到");
      } finally {if (fis != null) fis.close(); // 需处理IOException
      }
      
  • 使用throws声明抛出异常

    • 核心思想:将异常抛给调用者处理,当前方法不直接处理。

    • 适用场景:当前方法无法处理异常(如工具类方法、底层逻辑),需由上层调用者决定如何应对。

    • 示例

      public void readFile() throws FileNotFoundException, IOException {FileReader file = new FileReader("test.txt");// 其他可能抛出 IOException 的操作
      }
      
  • throw抛出异常

    • 手动抛出异常对象,可以是自定义异常。

    • 示例

      if (age < 0) {throw new IllegalArgumentException("年龄不能为负数");
      }
      

自定义异常

  • 步骤

    • 继承 Exception(检查型异常)或 RuntimeException(非检查型异常)。
    • 提供构造方法(通常调用父类构造)。
  • 示例

    public class InsufficientFundsException extends RuntimeException {public InsufficientFundsException(String message) {super(message);}
    }// 使用
    if (balance < amount) {throw new InsufficientFundsException("余额不足");
    }
    

Error 和 Exception 的区别?

  • Error:JVM 严重问题(如内存溢出),程序无法恢复。
  • Exception:可捕获处理的异常(检查型需处理,非检查型通常不强制)。

22.为什么String类可以不用new创建对象?

在Java中,String类可以不用new关键字创建对象,这是由**字符串常量池(String Pool)**机制和Java对字符串字面量的特殊处理共同实现的。

字符串常量池(String Pool)

  • 什么是字符串常量池?

    字符串常量池是Java堆内存中的一块特殊存储区域,用于缓存字符串字面量。当通过字面量(如"abc")创建字符串时,JVM会先在字符串常量池中检查是否存在相同内容的字符串:

    • 如果存在:直接返回池中已有字符串的引用,不创建新对象
    • 如果不存在:在池中创建该字符串对象,并返回引用。
  • 目的:减少重复字符串的内存占用,提升性能。

  • 示例

    String s1 = "abc";  // 第一次创建,池中没有,故在池中新建对象
    String s2 = "abc";  // 直接复用池中的"abc",s1和s2指向同一对象
    System.out.println(s1 == s2); // 输出 true(引用相同)
    

new String()与字面量的区别

  • 使用new关键字

    每次都会在堆中强制创建新对象,即使内容相同。

    String s3 = new String("abc"); // 在堆中新建对象,不检查常量池
    String s4 = new String("abc"); // 再新建一个对象
    System.out.println(s3 == s4); // 输出 false(引用不同)
    
  • 使用字面量

    直接利用常量池,避免重复构建。

    String s5 = "abc"; // 从常量池获取
    String s6 = "abc"; // 同上
    System.out.println(s5 == s6); // 输出 true(引用相同)
    

字符串的不可变性

  • String类被设计为不可变(所有修改操作都返回新对象),这使得常量池可以安全地缓存字符串:
    • 多个引用共享同一字符串时,无需担心内容被意外修改。
    • 缓存字符串的哈希值,提升性能(如HashMap的键)。

编译时优化

  • 字面量的处理

    在编译阶段,字符串字面量会被直接写入类的常量池。当类加载时,JVM会将这些字面量预先加载到字符串常量池中。

    String s7 = "hello" + " world"; // 编译期优化为"hello world"
    // 等价于 String s7 = "hello world";
    

intern方法

手动将字符串添加到常量池:调用intern()方法时,如果池中已有相同内容的字符串,返回其引用;否则将当前字符串添加到池中。

String s8 = new String("xyz").intern();
String s9 = "xyz";
System.out.println(s8 == s9); // 输出 true

总结

Java通过字符串常量池和字面量处理机制,使得直接赋值(如"abc")能够复用已有对象,无需显式使用new。这种处理能够节省内存、提升性能,同时依赖字符串的不可变性保证安全性。

23.增强for

增强 for 循环(也称为 for-each 循环)是 Java 5 引入的语法糖,旨在简化集合和数组的遍历操作。它隐藏了迭代器或索引的细节,使代码更简洁易读。

基本语法

for (元素类型 变量名 : 集合或数组) {// 操作变量
}

示例

List<String> list = Arrays.asList("A", "B", "C");
for (String s : list) {System.out.println(s);  // 输出 A, B, C
}int[] array = {1, 2, 3};
for (int num : array) {System.out.println(num);  // 输出 1, 2, 3
}

原理

  • 遍历数组:编译器会将其转换为传统索引循环

    // 源码:for (int num : array) { ... }
    for (int i = 0; i < array.length; i++) {int num = array[i];// 操作 num
    }
    
  • 遍历集合:编译器会调用集合的 iterator() 方法,使用迭代器遍历

    // 源码:for (String s : list) { ... }
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {String s = iterator.next();// 操作 s
    }
    

注意事项

  • 无法直接访问索引

    若需索引,需改用传统 for 循环或额外计数变量。

    int index = 0;
    for (String s : list) {System.out.println(index + ": " + s);index++;
    }
    
  • 不能修改集合结构

    遍历时直接调用集合的 add()remove() 会抛出 ConcurrentModificationException

相关文章:

Java入门首周精要:从基础语法到面向对象核心解析

文章目录 Java入门首周精要&#xff1a;从基础语法到面向对象核心解析1.Java类名与文件名的一致性规则2.Java和C语言中char类型的区别3.Java中的注释4.Java中的‘’‘’运算符5.Java的输入输出6.方法&#xff08;重载&重写&#xff09;方法的重载方法的重写 7.面向对象&…...

嵌入式AI开源生态指南:从框架到应用的全面解析

嵌入式AI开源生态指南&#xff1a;从框架到应用的全面解析 引言 随着人工智能技术的迅速发展&#xff0c;将AI能力部署到边缘设备上的需求日益增长。嵌入式AI通过在资源受限的微控制器上运行机器学习模型&#xff0c;实现了无需云连接的本地智能处理&#xff0c;大幅降低了延…...

MCP server的stdio和SSE分别是什么?

文章目录 一、Stdio:本地进程间通信的核心二、SSE:远程通信与实时推送的利器三、Stdio vs SSE:关键差异对比四、如何选择?场景驱动的决策指南五、实战建议与避坑指南实际操作结语在AI应用开发中,MCP(Model Context Protocol)协议正成为连接大模型与外部资源的核心桥梁。…...

哈希表(闭散列)的实现

目录 概念及定义 闭散列的介绍 闭散列底层实现 哈希表的定义 哈希表的构造 哈希表扩容 哈希表插入 哈希表删除 哈希表查找 概念及定义 哈希表&#xff0c;也成为散列表&#xff0c;在C中unordered_set和unordered_map的底层实现依靠的都是哈希表。 map和set的底层是红…...

Shiro学习(六):Shiro整合CAS实现单点登录

一、单点登录介绍 单点登录&#xff08;Single Sign On&#xff09;&#xff0c;简称为 SSO&#xff0c;是比较流行的企业业务整合的解决方案之一。 SSO的定义是在多个[应用]&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统。 一般这种单点登录的实现方案&…...

HAProxy-ACL实战篇

HAProxy-ACL实战篇 IP说明172.25.254.101客户端172.25.254.102haproxy服务器172.25.254.103web1172.25.254.104web2 ACL示例-域名匹配 # 172.25.254.102 [rootRocky ~]# cat /etc/haproxy/conf.d/test.cfg frontend magedu_http_portbind 172.25.254.102:80mode httpbalanc…...

以下是针对该 Ansible 任务的格式检查和优化建议

以下是针对该 Ansible 任务的格式检查和优化建议&#xff1a; 目录 一、格式检查原始代码问题分析修正后的标准格式 二、推荐增强功能1. 添加可执行权限2. 显式指定 Shell 解释器3. 添加错误处理 三、完整 Playbook 示例四、验证脚本兼容性五、常见错误总结 一、格式检查 原始…...

C++语言的测试覆盖率

C语言的测试覆盖率分析与实践 引言 在软件开发过程中&#xff0c;测试覆盖率是一项重要的质量指标&#xff0c;它帮助开发者评估代码的测试效果&#xff0c;确保软件的可靠性与稳定性。尤其在C语言的开发中&#xff0c;由于其复杂的特性和丰富的功能&#xff0c;测试覆盖率的…...

如何使用 DrissionPage 进行网页自动化和爬取

在这个技术博客中&#xff0c;我们将向大家展示如何使用 DrissionPage 进行网页自动化操作与数据爬取。DrissionPage 是一个基于 Playwright 的 Python 自动化工具&#xff0c;它允许我们轻松地控制浏览器进行网页爬取、测试以及自动化操作。与其他工具&#xff08;如 Selenium…...

设计模式 Day 3:抽象工厂模式(Abstract Factory Pattern)详解

经过前两天的学习&#xff0c;我们已经掌握了单例模式与工厂方法模式&#xff0c;理解了如何控制实例个数与如何通过子类封装对象的创建逻辑。 今天&#xff0c;我们将进一步深入“工厂”体系&#xff0c;学习抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&a…...

TensorRT 有什么特殊之处

一、TensorRT的定义与核心功能 TensorRT是NVIDIA推出的高性能深度学习推理优化器和运行时库&#xff0c;专注于将训练好的模型在GPU上实现低延迟、高吞吐量的部署。其主要功能包括&#xff1a; 模型优化&#xff1a;通过算子融合&#xff08;合并网络层&#xff09;、消除冗余…...

SQL注入-盲注靶场实战(手写盲注payload)--SRC获得库名即可

布尔盲注 进入页面 注入点 ’ and 11 and 12 得知为布尔盲注 库名长度 and length(database()) 8 抓包&#xff08;浏览器自动进行了url编码&#xff09;爆破 得知为 12 库名字符 1 and ascii(substr(database(),1,1))112 – q &#xff08;这里如果不再次抓包…...

http://noi.openjudge.cn/_2.5基本算法之搜索_1804:小游戏

文章目录 题目深搜代码宽搜代码深搜数据演示图总结 题目 1804:小游戏 总时间限制: 1000ms 内存限制: 65536kB 描述 一天早上&#xff0c;你起床的时候想&#xff1a;“我编程序这么牛&#xff0c;为什么不能靠这个赚点小钱呢&#xff1f;”因此你决定编写一个小游戏。 游戏在一…...

Windows Flip PDF Plus Corporate PDF翻页工具

软件介绍 Flip PDF Plus Corporate是一款功能强大的PDF翻页工具&#xff0c;也被称为名编辑电子杂志大师。这款软件能够迅速将PDF文件转换为具有翻页动画效果的电子书&#xff0c;同时保留原始的超链接和书签。无论是相册、视频、音频&#xff0c;还是Flash、视频和链接&#…...

Java八股文-List

集合的底层是否加锁也就代表是否线程安全 (一)List集合 一、数组 array[1]是如何通过索引找到堆内存中对应的这块数据的呢? (1)数组如何获取其他元素的地址值 (2)为什么数组的索引是从0开始的&#xff0c;不可以从1开始吗 (3)操作数组的时间复杂度 ①查找 根据索引查询 未…...

btrfs , ext4 , jfs , xfs , zfs 对比 笔记250406

btrfs , ext4 , jfs , xfs , zfs 对比 笔记250406 特性Btrfsext4JFSXFSZFS定位现代多功能传统稳定轻量级高性能大文件企业级存储最大文件/分区16EB / 16EB16TB / 1EB4PB / 32PB8EB / 8EB16EB / 25610⁵ ZB快照✅ 支持❌ 不支持❌ 不支持❌ 不支持✅ 支持透明压缩✅ (Zstd/LZO)❌…...

Meta上新Llama 4,到底行不行?

这周AI圈被Meta的“深夜突袭”炸开了锅。 Llama 4家族带着三个新成员&#xff0c;直接杀回开源模型战场&#xff0c;连扎克伯格都亲自站台喊话&#xff1a;“我们要让全世界用上最好的AI&#xff01;” 但别急着喊“王炸”&#xff0c;先看看它到底强在哪。 这次Meta玩了个狠招…...

显示器工艺简介

华星光电显示器的生产工艺流程介绍&#xff0c;从入厂原料到生产出显示器的整体工艺介绍 华星光电显示器的生产工艺流程主要包括以下几个阶段&#xff0c;从原材料入厂到最终显示器的生产&#xff1a; 原材料准备 玻璃基板&#xff1a;显示器的核心材料&#xff0c;通常采用超…...

音乐软件Pro版!内置音源,听歌自由,一键畅享!

今天给大家介绍一款超实用的音乐软件——LX音乐Pro版。原版LX音乐需要用户自行导入音源才能正常使用&#xff0c;但此次推出的Pro版已经内置了音源&#xff0c;省去了繁琐的操作步骤&#xff0c;使用起来更加便捷 这款软件不仅支持歌曲搜索&#xff0c;还能搜索歌单&#xff0c…...

Spring 中有哪些设计模式?

&#x1f9e0; 一、Spring 中常见的设计模式 设计模式类型Spring 中的应用场景单例模式创建型默认 Bean 是单例的工厂模式创建型BeanFactory、FactoryBean抽象工厂模式创建型ApplicationContext 提供多个工厂接口代理模式结构型AOP 动态代理&#xff08;JDK/CGLIB&#xff09;…...

R语言使用ggplot2作图

在ggplot2中&#xff0c;图是采用串联起来&#xff08;&#xff09;号函数创建的。每个函数修改属于自己的部分。比如&#xff0c;ggplot()geom()...... aes(x, y, colour a,shape a,size a.......) ggplot2中画图常用的五大块内容 数据(data)及一系列将数据中的变量对应到图…...

GenerationMixin概述

类 类名简单说明GenerateDecoderOnlyOutput继承自 ModelOutput&#xff0c;适用于非束搜索方法的解码器-only模型输出类。GenerateEncoderDecoderOutput继承自 ModelOutput&#xff0c;适用于非束搜索方法的编码器-解码器模型输出类。GenerateBeamDecoderOnlyOutput继承自 Mod…...

文心快码制作微信小程序

AI时代来临&#xff0c;听说Baidu Comate也推出了自家的编程工具Zulu&#xff0c;可以从零到一帮你生成代码&#xff0c;趁着现在还免费&#xff0c;试试效果如何。这里以开发一个敲木鱼的微信小程序为例 一、需求分析 写小程序需求文档 首先&#xff0c;第一步我要准确描述…...

flutter provider状态管理使用

在 Flutter 中&#xff0c;Provider 是一个轻量级且易于使用的状态管理工具&#xff0c;它基于 InheritedWidget&#xff0c;并提供了一种高效的方式来管理和共享应用中的状态。相比其他复杂的状态管理方案&#xff08;如 Bloc 或 Riverpod&#xff09;&#xff0c;Provider 更…...

C++——静态成员

目录 静态成员的定义 静态成员变量 编程示例 存在的意义 静态成员函数 类内声明 类外定义 编程示例 静态成员的定义 静态成员在C类中是一个重要的概念&#xff0c;它包括静态成员变量和静态成员函数。静态成员的特点和存在的意义如下&#xff1a; 静态成员变量 1…...

UDP学习笔记(四)UDP 为什么大小不能超过 64KB?

&#x1f310; UDP 为什么大小不能超过 64KB&#xff1f;TCP 有这个限制吗&#xff1f; 在进行网络编程或者调试网络协议时&#xff0c;我们常常会看到一个说法&#xff1a; “UDP 最大只能发送 64KB 数据。” 这到底是怎么回事&#xff1f;这 64KB 是怎么来的&#xff1f;TCP…...

Linux中用gdb查看coredump文件

查看dump的命令&#xff1a; gdb 可执行文件 dump文件路径查看函数调用栈 (gdb)bt查看反汇编代码 (gdb)disassemble查看寄存器的值 (gdb)info all-registers如果通过上述简单命令无法排查&#xff0c;还是通过-g参数编译带符号表的可执行文件&#xff0c;再用gdb查看...

PyTorch 深度学习 || 7. Unet | Ch7.1 Unet 框架

1. Unet 框架...

LeetCode 热题 100 堆

215. 数组中的第K个最大元素 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 **k** 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 …...

LeetCode栈 155. 最小栈

设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void pop() 删除堆栈顶部的元素。int top() 获取堆栈顶部的元素。int get…...

Linux系统03---文件操作时间编程

目录 文件操作 1.1 缓冲区 1.2 基于缓冲区的文件操作---高级 IO 1.3 基于非缓冲区的文件操作—低级 IO 1.3.1 文件描述符 int fd; 1.3.2 函数名&#xff1a;open() 1.3.3 函数名&#xff1a;close() 1.3.4 函数名&#xff1a;write() 1.3.5 函数名&#xff1a;read(…...

4月5日作业

需求&#xff1a; 1.按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2.要求SW 1为VLAN 2/3的主根及主网关 SW2为VLAN 20/30的主根及主网关&#xff0c;SW1和 SW2互为备份 3.可以使用super vlan 4.上层通过静态路由协议完成数据通信过程 5.AR1为企业出口路由器…...

新一代AI架构实践:数字大脑AI+智能调度MCP+领域执行APP的黄金金字塔体系

新一代AI架构实践&#xff1a;数字大脑智能调度领域执行的黄金金字塔体系 一、架构本质的三层穿透性认知 1.1 核心范式转变&#xff08;CPS理论升级&#xff09; 传统算法架构&#xff1a;数据驱动 → 特征工程 → 模型训练 → 业务应用 新一代AI架构&#xff1a;物理规律建…...

低代码开发:重塑软件开发的未来

在数字化转型的浪潮中&#xff0c;企业对软件开发的需求呈爆炸式增长。然而&#xff0c;传统软件开发模式面临着开发周期长、成本高、技术门槛高等诸多挑战。低代码开发平台&#xff08;Low-Code Development Platform&#xff09;应运而生&#xff0c;它通过可视化编程和拖拽式…...

小型园区网实验作业

拓扑搭建&#xff1a; 实验需求&#xff1a; 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及网关 SW2 为VLAN 20/30 的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan 4、上层通过静态路由协议完成数据通信过程 5、A…...

Gateway 网关 快速开始

一、核心概念 路由&#xff08;route) 路由是网关中最基础的部分&#xff0c;路由信息包括一个ID、一个目的URI、一组断言工厂、一组Filter组成。如果断言为真&#xff0c;则说明请求的 URL 和配置的路由匹配。 断言(predicates) 断言函数允许开发者去定义匹配 Http Request 中…...

C++中如何使用STL中的list定义一个双向链表,并且实现增、删、改、查操作

一、STL中的 list 是双向链表&#xff0c;但不是循环链表&#xff0c;通过指针访问结点数据&#xff0c;它的内存空间可以是不连续的&#xff0c;使用它能高效地进行各种操作。 二、代码 #include <bits/stdc.h> using namespace std;// 打印链表元素的函数 void print…...

shell脚本中捕获键盘中断信号trap

在 Shell 脚本中&#xff0c;可以通过 trap 命令捕获键盘中断信号&#xff08;通常是 SIGINT&#xff0c;即 CtrlC&#xff09;。以下是具体的实现方法&#xff1a; 1.使用 trap 捕获键盘中断信号 trap 命令用于捕获信号并执行相应的命令或函数。SIGINT&#xff08;信号编号为 …...

让ChatGPT用DeepReaserch指导进行学术写作

目录 ChatGPT在学术论文写作中的作用与分阶段提示词指南 1.选题阶段&#xff08;确定研究课题方向&#xff09; 2.文献综述阶段&#xff08;调研与综述已有研究&#xff09; 3.研究设计阶段&#xff08;设计研究方法与框架&#xff09; 4.撰写正文阶段&#xff08;撰写各部…...

Compose笔记(十四)--LazyColumn

这一节了解一下Compose中的LazyColumn&#xff0c;在Jetpack Compose 中&#xff0c;LazyColumn 是一个用于高效显示长列表或可滚动垂直布局的组件。它类似于传统 Android 开发中的 RecyclerView&#xff0c;但专为 Compose 的声明式 UI 框架设计&#xff0c;能够显著优化性能&…...

CNN-SE-Attention-ITCN多特征输入回归预测(Matlab完整源码和数据)

CNN-SE-Attention-ITCN多特征输入回归预测&#xff08;Matlab完整源码和数据&#xff09; 目录 CNN-SE-Attention-ITCN多特征输入回归预测&#xff08;Matlab完整源码和数据&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.一种适合光伏功率回归预测的高创…...

Spring Data JPA中的List底层:深入解析ArrayList的奥秘!!!

&#x1f31f; Spring Data JPA中的List底层&#xff1a;深入解析ArrayList的奥秘 &#x1f4a1; 你是否好奇过&#xff0c;为什么Spring Data JPA的查询方法返回的List<T>总是默认为ArrayList&#xff1f;本文将通过技术原理解析、验证实验和性能优化指南&#xff0c;为…...

redis高并发缓存架构与性能优化

Redlock实现原理 超过半数redis节点加锁成功才算成功加锁。 Redlock存在问题 如果主节点挂掉&#xff0c;还没有同步到从节点&#xff0c;重新选举出主节点&#xff0c;那加锁就没有加到这个新的主节点上。 如果增加redis主节点数&#xff0c;那么加锁的性能更差&#xff0c;要…...

解锁多邻国:全方位语言学习新体验

解锁多邻国&#xff1a;全方位语言学习新体验​ ​ 在数字化学习浪潮中&#xff0c;多邻国&#xff08;Duolingo&#xff09;凭借独特优势&#xff0c;成为全球超 5 亿用户的语言学习首选。这款 2012 年诞生于美国匹兹堡的应用&#xff0c;2019 年进入中国市场后&#xff0c;…...

Docker部署SeraXNG接入dify报错解决

报错&#xff1a; 设置授权 配置凭据后&#xff0c;工作区中的所有成员都可以在编排应用程序时使用此工具。 SearXNG base URL* 如何获取 PluginInvokeError: {"args":{},"error_type":"ToolProviderCredentialValidationError","message&q…...

Zookeeper的作用详解

Zookeeper作为分布式协调服务&#xff0c;在分布式系统中承担核心协调角色&#xff0c;其作用可归纳为以下核心功能模块&#xff1a; 一、分布式协调与同步 分布式锁管理 提供独占锁和共享锁&#xff0c;通过创建临时顺序节点实现锁的公平竞争。例如&#xff0c;客户端在/distr…...

高频面试题(含笔试高频算法整理)基本总结回顾34

干货分享&#xff0c;感谢您的阅读&#xff01; &#xff08;暂存篇---后续会删除&#xff0c;完整版和持续更新见高频面试题基本总结回顾&#xff08;含笔试高频算法整理&#xff09;&#xff09; 备注&#xff1a;引用请标注出处&#xff0c;同时存在的问题请在相关博客留言…...

Dify 与 n8n 对比分析:AI 应用开发与自动化工作流工具的深度比较

Dify 与 n8n 对比分析&#xff1a;AI 应用开发与自动化工作流工具的深度比较 摘要 本文对比分析了 Dify 和 n8n 两款工具的核心定位、功能特点、适用场景及技术门槛。Dify 专注于 AI 应用开发&#xff0c;适合快速搭建智能客服、知识库检索等场景&#xff1b;n8n 则定位于通用…...

Systemd构建容器化微服务集群管理系统

实训背景 你是一家云计算公司的 DevOps 工程师&#xff0c;需为某客户设计一套基于 Docker 的微服务集群管理系统&#xff0c;需求如下&#xff1a; 容器自启管理&#xff1a;确保三个服务&#xff08;webapp、api、redis&#xff09;在系统启动时自动运行。依赖顺序控制&…...

手搓多模态-04 归一化介绍

在机器学习中&#xff0c;归一化是一个非常重要的工具&#xff0c;它能帮助我们加速训练的速度。在我们前面的SiglipVisionTransformer 中&#xff0c;也有用到归一化层&#xff0c;如下代码所示&#xff1a; class SiglipVisionTransformer(nn.Module): ##视觉模型的第二层&am…...