JAVA SE重点

JAVA SE重点

  1. 数据类型部分
    • 8种基本类型 :byte, char, short, int, long, float, double, boolean。要记住它们的默认值和取值范围,比如char的默认值是'\u0000',boolean默认是false
    • 引用类型:String、数组、接口、类、枚举等。
    • 整形提升 :这是常考的坑点,比如 byte a = 10; byte b = 20; byte c = a + b;会报错,因为a+b会自动提升为int类型,需要强转 (byte)(a+b)
    • 布尔类型转换:任何类型和布尔类型都不能相互转换,这点要特别注意。
  2. 常量
    • final修饰的变量是常量,只能赋值一次,不能被修改。
    • 字面值是直接写出来的常量,比如 5, "hello", 12.21
  3. 运算符
    • >>>是无符号右移,没有无符号左移。
    • %是取余/取模,注意它的正负号规则(与被除数符号一致)。
  4. 逻辑控制
    • switch:重点记不能做switch参数的类型:long, float, double。
    • 循环语句:do-while至少执行一次;for-each常用于遍历数组或集合,面试常问for和for-each的区别(for-each更简洁但不能修改元素,不能获取索引,不能处理非数组/集合对象)。
  5. 命名规则
    • 小驼峰命名法:首字母小写,后面单词首字母大写,如 maxNum
    • 标识符可以包含数字、字符、下划线、$。

JDK 常用命令

  1. javac
  • 作用 :Java 编译器,用于将 .java源文件编译成 .class字节码文件。

  • 示例

    复制代码
    javac HelloWorld.java

    会生成 HelloWorld.class文件。

  1. java
  • 作用 :Java 虚拟机启动器,用于运行已编译的 .class文件(不需要加 .class后缀)。

  • 示例

    复制代码
    java HelloWorld

    会执行 HelloWorld类中的 main方法。

  1. javap -c
  • 作用 :反汇编器,用于查看 .class文件的字节码指令(-c表示只显示反汇编的代码)。

  • 示例

    复制代码
    javap -c HelloWorld.class

    可以查看方法内部的字节码操作,常用于底层调试或学习 JVM 指令。

记忆口诀

"编 javac,跑 java,反 javap -c看字节码。"

面试常见问题

  • javacjava的区别?
    • javac是编译器,java是运行时启动器。
  • javap -c有什么用?
    • 查看类的字节码指令,用于分析 JVM 执行过程。

一、方法的定义与作用

  • 核心作用 :模块化组织代码,实现复用(避免重复写相同逻辑)。
  • 组成要素 :方法名、参数列表、返回值(返回值可以是void,表示无返回值)。

二、方法的调用方式

  • 调用位置

    • 可以在主函数(main)中调用其他自定义方法。
    • 也可以在其他自定义方法的内部调用(方法嵌套调用)。
  • 调用规则

    • 方法名和参数列表必须严格匹配(个数、类型都要对应)。
    • 返回值类型可选:如果方法声明有返回值(如int),调用时需接收;如果是void,则不能接收返回值。

面试常考题(重点!):

给定两个数字,写一个方法交换它们的值。

  • ❗ 陷阱:Java是值传递!如果直接传基本类型变量(如int a, int b),方法内交换不会影响外部变量。

  • ✅ 正确做法:传对象(如数组、自定义类)或使用数组包装。

  • 示例代码:

    复制代码
    void swap(int[] arr) {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp;
    }
    // 调用:swap(new int[]{a, b});

三、方法的重载(Overloading)------面试高频考点!

  • 定义 :在同一个类中,方法名相同,参数列表不同 (参数个数不同 / 参数类型不同 / 参数顺序不同),返回值类型无关

  • 示例

    复制代码
    void sum(int);         // 重载1:1个int参数
    int sum(int, int);     // 重载2:2个int参数
    int sum(double, double); // 重载3:2个double参数

    👉 这三个方法在编译时都能区分,不会冲突。

  • 构造方法能否重载?

    • ✅ 可以!因为构造方法名固定为类名,只要参数列表不同,就可以重载。
    • 举例:Student()Student(String name)Student(String name, int age)都是合法重载。
  • 易错点

    • 仅返回值不同 ≠ 重载(编译报错)。
    • 仅参数名不同 ≠ 重载(参数名不影响签名)。

四、方法的递归(Recursion)------思维+代码双重考验

  • 基本思想:将大问题拆解为规模更小的同类子问题,子问题再继续拆解,直到能直接解决。

    如:求阶乘 n! = n * (n-1)!,直到 1! = 1

  • 核心注意事项

    1. 必须有终止条件(递归出口)→ 否则无限递归,导致栈溢出(StackOverflowError)。
    2. 每次递归必须向终止条件靠近 → 否则死循环。
    3. 自己调用自己 → 递归的本质是自调用。
  • 经典例题

    • 斐波那契数列:f(n) = f(n-1) + f(n-2),终止条件 f(1)=1, f(2)=1
    • 汉诺塔问题、二叉树遍历等。

🔥 总结:面试/笔试必背点

知识点 关键点
方法定义 模块化、可复用;组成:方法名、参数列表、返回值
方法调用 参数匹配、返回值接收;交换实参值需传对象或数组(值传递陷阱)
方法重载 同一类中,方法名相同 + 参数列表不同;返回值无关;构造方法可重载
递归 拆解问题 + 终止条件 + 自身调用;防止栈溢出

一、数组的定义

  • 本质 :数组是存放一组相同数据类型 的集合,且在内存中是连续的。

  • 默认值

    • 简单类型(如intbyte):未赋值时默认值为 0(或对应类型的默认值,如boolean默认false)。
    • 引用类型(如String、自定义类):未赋值时默认值为 null
  • 示例

    复制代码
    int[] arr1 = new int[5]; // 5个int的默认值都是0
    String[] arr2 = new String[3]; // 3个String的默认值都是null

二、数组作为方法的参数

  • 引用类型传递 :数组是引用类型,传参时传递的是引用(地址),而非副本。因此,方法内修改数组元素,会影响原数组。

    复制代码
    void modify(int[] arr) {
        arr[0] = 100; // 修改原数组的第0个元素
    }
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        modify(arr);
        System.out.println(arr[0]); // 输出100
    }
  • 可变参数编程int sum(int... a)表示可以传入任意个数的int参数(本质是数组)。调用时既可以传数组,也可以传多个int值。

    复制代码
    int sum(int... a) {
        int res = 0;
        for (int num : a) res += num;
        return res;
    }
    // 调用:sum(1,2,3) 或 sum(new int[]{1,2,3})

三、JVM内存划分(数组的内存位置)

JVM运行时内存分为5个区域,数组相关的内存分配如下:

  • 程序计数器:记录线程执行的字节码行号,与数组无关。
  • Java虚拟机栈 :存储局部变量、方法调用栈帧。如果数组是局部变量 (如在方法中定义的数组),其引用存在栈中,但数组本身在中。
  • 本地方法栈:与本地方法(Native Method)有关,与数组无关。
  • :存储对象(包括数组)的实例,数组的实际数据在堆中。
  • 方法区 :存储类的元数据、常量池等。如果数组元素是引用类型(如String),字符串常量可能在方法区的常量池中。

四、数组的拷贝方式(重点:浅拷贝)

数组拷贝需要注意:如果数组元素是引用类型,拷贝的是引用(浅拷贝),即新数组和原数组的元素指向同一个对象。

常见拷贝方式:

  1. for循环:手动遍历复制每个元素。

  2. clone()Object类的方法,数组实现了Cloneable接口,可调用arr.clone()

  3. System.arraycopy():底层native方法,效率高。

    复制代码
    int[] src = {1,2,3};
    int[] dest = new int[3];
    System.arraycopy(src, 0, dest, 0, 3); // 从src的0位置复制3个元素到dest的0位置
  4. Arrays.copyOf():基于System.arraycopy封装,支持扩容/缩容。

    复制代码
    int[] newArr = Arrays.copyOf(src, 5); // 复制src并扩容到长度5,新元素默认值0

五、操作数组的常用工具类:java.util.Arrays

  • Arrays.toString(arr) :将数组转为字符串,方便打印(默认print(arr)会输出地址,用这个方法可读性更好)。

    复制代码
    int[] arr = {1,2,3};
    System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3]
  • Arrays.sort(arr) :对数组排序(升序)。如果是自定义类,需要实现Comparable接口或传入Comparator

    复制代码
    int[] arr = {3,1,2};
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr)); // 输出 [1, 2, 3]

六、二维数组

  • 内存结构 :二维数组本质上是"一维数组的每个元素是一个一维数组"。

    复制代码
    int[][] arr = new int[3][]; // 不规则二维数组:3行,每行长度可不同
    arr[0] = new int[2]; // 第0行长度2
    arr[1] = new int[3]; // 第1行长度3
    arr[2] = new int[1]; // 第2行长度1
  • 不规则二维数组:允许每行的列数不同(即"锯齿状"数组)。

七、匿名数组

  • 定义:没有名字的数组,通常用于一次性传递数组参数(不需要先声明数组变量)。

  • 示例:

    复制代码
    // 调用方法时直接传匿名数组
    int sum = sum(new int[]{1,2,3,4});

关键易错点总结

  1. 数组默认值 :基本类型是0/false等,引用类型是null
  2. 数组拷贝的浅拷贝:如果元素是引用类型,拷贝后新数组和原数组的元素共享对象。
  3. 二维数组的内存:先分配"行"的数组,再分配每行的数组。
  4. 可变参数int... a本质是数组,只能有一个可变参数,且必须在参数列表最后。

一、类与对象的基本概念

  • :是模板(蓝图),定义了对象的属性(字段)和行为(方法)。
  • 对象 :是类的实体 (实例),通过 new 类名()创建,一个类可实例化多个对象。

二、类的成员(字段、方法、代码块)

  • 字段(属性) :对象的状态(如 Person类的 nameage)。
  • 方法(行为) :对象的动作(如 Person类的 eat()run())。
  • 代码块
    • 静态代码块 :用 static{}修饰,优先执行(与静态属性声明顺序有关),仅执行一次,用于初始化静态资源。
    • 实例代码块(构造代码块) :用 {}修饰,在构造方法前执行,用于初始化实例属性(可看作构造方法的"公共逻辑")。

三、内部类(面试高频考点)

内部类是定义在类内部的类,分为4类,需重点掌握实例内部类静态内部类

  1. 实例内部类(非静态内部类)
  • 定义:在类内部,无 static修饰。

  • 特点:

    • 包含外部类的 this引用,有额外开销(内存占用略高)。
    • 不能定义静态成员变量 (除非是 static final常量,因为常量在编译期确定)。
  • 面试问题:

    • Q:实例内部类是否有额外开销?

      A:有,因为持有外部类的引用。

    • Q:实例内部类能否定义静态成员变量?

      A:不能,除非是 static final修饰的常量。

  1. 静态内部类
  • 定义:在类内部,被 static修饰。

  • 特点:

    • 不依赖外部类实例,可直接通过 外部类名.内部类名访问。
    • 不能访问外部类的非静态成员 (因为静态内部类没有外部类的 this引用)。
  • 面试问题:

    • Q:静态内部类能否访问外部类的非静态成员?

      A:不能。若需访问,需传入外部类对象。

  1. 匿名内部类
  • 定义:没有名字的内部类,是外部类的子类(或实现类),只能用一次

  • 本质:语法糖,简化代码(如线程、接口回调场景)。

    复制代码
    // 匿名内部类实现Runnable接口
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("匿名内部类");
        }
    }).start();
  1. 本地内部类(了解)
  • 定义:在方法内部定义的类,作用域仅限方法内。

四、访问类的属性/方法

  • 静态成员 (用 static修饰):
    • 属于 ,可通过 类名.属性/方法访问(无需创建对象)。
  • 非静态成员 (实例成员):
    • 属于对象 ,需通过 对象引用.属性/方法访问(必须先 new对象)。

五、封装(面向对象三大特性之一)

  • 定义 :用 private修饰属性/方法,隐藏内部实现,对外提供 publicget/set方法访问。
  • 优点
    • 降低使用者学习成本(只需关注"如何使用",无需关注"如何实现")。
    • 保护数据安全(防止非法修改)。
  • 面试常考:封装的意义、如何实现封装。

六、构造方法(对象的"出生证明")

  • 定义 :方法名与类名相同,无返回值 (连 void都没有)。
  • 作用 :实例化对象时,为对象分配内存初始化属性
  • 调用时机new 类名()时自动调用(如 Person p = new Person();调用无参构造)。
  • 多个构造方法(重载)
    • 若类未显式定义构造方法 ,编译器会默认生成一个无参构造
    • 显式定义了构造方法 ,编译器不再生成默认无参构造 (需手动写无参构造,否则 new Person()会报错)。
  • 面试常考:构造方法的重载、默认构造的生成规则。

七、关键字 this

  • 含义 :代表当前对象的引用 (哪个对象调用方法,this就指向哪个对象)。
  • 常见场景
    • 区分成员变量和局部变量(如 this.name = name;)。
    • 构造方法间调用(需放在第一行,如 this(10);调用有参构造)。

八、toString()方法(Object类的方法)

  • 默认行为Object类的 toString()返回格式为 类名@哈希值(如 Person@123456)。

  • 重写意义:打印对象时,输出更有意义的信息(如对象的属性值)。

    复制代码
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
  • 使用 :直接打印对象引用时(如 System.out.println(p);),会自动调用 toString()

九、匿名对象

  • 定义 :没有名字的对象(如 new Person().eat();)。
  • 特点
    • 只能使用一次(因为没有引用指向它,GC 会回收)。
    • 适合临时调用方法,简化代码。

易错点总结

  1. 内部类的静态变量 :实例内部类不能有普通静态变量,只能是 static final常量。
  2. 构造方法的重载:若显式定义了有参构造,默认无参构造会消失,需手动添加。
  3. 静态成员访问:静态方法不能直接访问非静态成员(因为静态方法属于类,此时可能还没有对象)。
  4. 匿名内部类的使用场景:仅在需要一次性使用类时使用(如线程、接口回调)。

一、继承(extends)

  • 定义 :子类(派生类)通过 extends关键字继承父类(基类)的属性和方法(除构造方法外,所有构造方法会被显式调用)。

  • 关键字 super

    • 代表父类对象的引用
    • 用法:
      • super():调用父类的构造方法(必须放在子类构造方法的第一行)。
      • super.data:调用父类的数据成员
      • super.fun():调用父类的方法
    • 面试常考:thisvs super
      • this:代表当前对象的引用(可区分局部变量和成员变量)。
      • super:代表父类对象的引用(访问父类的成员)。
      • 区别:this()调用本类构造,super()调用父类构造;this可单独用,super不能。
  • 继承的优点

    1. 代码共享(子类复用父类代码,减少重复)。
    2. 提高重用性(父类方法/属性可被多个子类继承)。
    3. 提高可扩展性(子类可扩展父类功能)。
  • 面试问题:子类继承了父类的什么?

    答:除构造方法(显式调用)外,其他所有成员(字段、方法、静态成员等)都会被继承。

二、多态

  • 定义 :父类引用指向子类对象,且子类和父类有同名、同参数列表、同返回值的覆盖方法(重写)。运行时,调用的是子类的方法(运行时多态)。

  • 实现条件

    1. 向上转型 :父类引用指向子类对象(如 Animal a = new Cat();)。
    2. 方法重写:子类重写父类的方法(方法名、参数、返回值相同)。
    3. 代码层次:父类引用调用同名方法时,子类重写的方法会被执行(运行时绑定)。
  • 多态的好处

    • 降低类使用者的成本(只需知道对象有某个方法,无需关心具体类型)。
    • 封装的延伸(使用者无需了解实现细节,只需用方法)。
  • 面试常考:多态的理解?

    答:父类引用调用子类重写的方法,运行时执行子类逻辑。体现"一个接口,多种实现"。

  • 向下转型

    • 前提:先通过 instanceof判断(如 if (a instanceof Cat)),否则会报 ClassCastException
    • 用途:将父类引用转回子类引用,访问子类特有方法(如 Cat c = (Cat) a;)。

三、抽象类(abstract)

  • 定义 :包含抽象方法 (没有具体实现的方法,用 abstract修饰)的类。

  • 关键字 abstract

    • 修饰类:表示该类不能被实例化(只能被继承)。
    • 修饰方法:表示该方法没有方法体(必须由子类重写)。
  • 特点

    1. 不能被实例化(不能 new抽象类)。
    2. 属性可以是 public static final(常量),也可以是普通属性。
    3. 可以有非抽象方法(普通方法,提供默认实现)。
    4. 可以被继承(子类必须重写所有抽象方法,除非子类也是抽象类)。
  • 最大意义:为了被继承,强制子类实现抽象方法(规范子类行为)。

  • 面试问题:抽象类和接口的区别?

    答:

    • 抽象类:有构造方法、可有非抽象方法、属性无限制、单继承。

    • 接口:无构造方法、方法默认 public abstract(JDK8前)、属性必须是 public static final、多实现。

      (JDK8后接口可含 default/static方法,但核心区别仍存)

四、接口(interface)

  • 定义 :用 interface修饰,是一种完全抽象的类型(JDK8前),定义行为规范。
  • 特点
    1. 方法:JDK8前,方法默认 public abstract;JDK8后,可含 default(默认方法,有实现)和 static方法。
    2. 属性:必须是 public static final(常量,必须初始化)。
    3. 不能被实例化(不能 new接口)。
    4. 类通过 implements实现接口(可多实现,如 class A implements B, C)。
  • 意义 :弥补Java"单继承"的缺陷,实现多继承的效果(类可实现多个接口)。
  • 常用接口
    • Comparable:用于自定义对象的自然排序(实现 compareTo方法)。
    • Comparator:用于定制排序(实现 compare方法,更灵活)。
    • Cloneable:标记接口,实现后可通过 clone()复制对象(需重写 clone()并抛 CloneNotSupportedException)。

五、关键总结(面试/笔试必背)

特性 继承(extends) 抽象类(abstract) 接口(interface)
关键字 extends abstract interface
实例化 子类可实例化 不能实例化 不能实例化
方法 可继承父类方法 可含抽象/非抽象方法 JDK8前:全抽象;JDK8后:可含default/static
属性 继承父类属性 无限制(普通/静态/常量) 必须是public static final
继承/实现 单继承(类→类) 单继承(类→抽象类) 多实现(类→接口)
构造方法 子类调用父类构造(super) 有构造方法(供子类调用) 无构造方法

六、易错点提醒

  1. 继承时构造方法的调用 :子类构造方法第一行必须调用 super()(或隐式调用父类无参构造),否则编译错误。
  2. 多态的前提:必须有"继承/实现"+"方法重写"+"向上转型"。
  3. 抽象类的继承:子类必须重写所有抽象方法,除非子类也是抽象类。
  4. 接口的实现:类实现接口时,必须实现所有抽象方法(JDK8前),或实现非默认/非静态方法。
  5. 向下转型 :必须先 instanceof判断,否则抛 ClassCastException

一、String(字符串)

  1. 本质与常量池
  • 类型 :Java中String引用类型

  • 常量池(JDK1.7+) :字符串常量(如"hello")存放在堆中的常量池 ,相同字符串常量在常量池中只存一份(节省内存)。

  • 示例

    复制代码
    String str = "hello"; // "hello"放入常量池
    String str2 = "hello"; // 直接从常量池取,str == str2 为true
  • 方法:intern():将字符串放入常量池(若已存在则直接引用,不存在则创建后引用)。

    复制代码
    String s1 = new String("hello");
    String s2 = s1.intern(); // s2指向常量池的"hello",s2 == str 为true

2. 拼接性能对比(面试常考)

  • +拼接 :会产生大量临时对象 (每次+都新建StringBuildertoString),性能差。
  • append拼接StringBuilder/StringBufferappend方法是在原对象上修改,无临时对象,性能高。
  • 线程安全
    • StringBuffer:方法加了synchronized线程安全(但性能略低)。
    • StringBuilder:非线程安全,单线程下性能更高。
  • 选择策略
    • 单线程+大量拼接 → 用StringBuilder
    • 多线程+大量拼接 → 用StringBuffer
    • 少量拼接 → 可用+(编译器会优化为StringBuilder)。
  1. 面试常考:Stringvs StringBuffervs StringBuilder
维度 String StringBuffer StringBuilder
可变性 不可变 可变 可变
线程安全 安全(不可变) 安全(synchronized) 不安全
性能 拼接差(临时对象) 中等(锁开销) 最高(无锁)
适用场景 少量拼接、常量 多线程大量拼接 单线程大量拼接

二、异常(Exception)

  1. 概念
  • 作用 :程序异常时,按预设逻辑处理,让程序尽可能恢复正常并继续执行,同时保证代码清晰。
  • 体系
    • Throwable(顶层类)→ Error+ Exception
      • Error错误(如栈溢出、内存溢出),由程序员无法解决(只能重启或修改逻辑)。
      • Exception异常 ,分为:
        • 运行时异常(RuntimeException) :非受查异常(编译时不检查,如NullPointerExceptionArrayIndexOutOfBoundsException)。
        • 编译时异常(受查异常) :编译时必须处理(如IOExceptionSQLException),否则编译报错。
  1. 异常处理关键字
  • try-catch-finally

    • try:包裹可能异常的代码。
    • catch:捕获并处理异常(可多个catch,子类在前,父类在后)。
    • finally无论是否异常,都会执行(一般用于释放资源,如关闭文件、数据库连接)。

throws:声明异常(告诉调用者"我这个方法可能抛异常,你自己处理")。

  • throw :手动抛出异常(如throw new RuntimeException("出错了"))。
  1. 面试问题
  • Q:finally块的作用?

    A:一般用于对资源的释放 (如关闭流、数据库连接),确保即使发生异常,资源也能被正确释放。finally无论try是否异常都会执行(除非JVM退出或System.exit())。

  • Q:如何处理异常?

    A:两种方式:

    1. try-catch-finally:捕获并处理。
    2. throws:声明抛出,交给调用者处理。
  • Q:自定义异常?

    A:继承Exception(受查异常)或RuntimeException(非受查异常),提供构造方法。

    复制代码
    class MyException extends Exception {
        public MyException(String msg) {
            super(msg);
        }
    }
  1. 关键注意点
  • Error是错误,程序无法处理,只能修改逻辑。
  • 运行时异常(如NullPointerException)是程序逻辑错误,应尽量在编码阶段避免(如判空)。
  • 编译时异常必须处理(try-catchthrows),否则编译失败。
  • finally中如果有return,会覆盖 trycatch中的return(不建议在finallyreturn)。

总结

  • String :重点是常量池、intern()、拼接性能对比、三者的区别。
  • 异常 :重点是异常体系、处理关键字(try-catch-finallythrowsthrow)、自定义异常、面试常见问题。
相关推荐
-Marks-4 小时前
【C++编程】STL简介 --- (是什么 | 版本发展历程 | 六大组件 | 重要性缺陷以及如何学习)
开发语言·c++·学习·stl·stl版本
PH = 74 小时前
OverlayFS联合文件系统使用示例
java·linux·服务器
HealthScience4 小时前
【Bib 2026】基因最新综述(有什么任务、benchmark、代表性模型)
android·开发语言·kotlin
wjs20244 小时前
CSS 网格元素
开发语言
AC赳赳老秦4 小时前
OpenClaw进阶技巧:批量修改文件内容、替换关键词,解放双手
java·linux·人工智能·python·算法·测试用例·openclaw
Java小白笔记5 小时前
OpenClaw 实战方法论
java·开发语言·人工智能·ai·全文检索·ai编程·ai写作
CoderCodingNo5 小时前
【信奥业余科普】C++ 的奇妙之旅 | 12:程序的交互与加工——数据的输入与算术运算
开发语言·c++
呱牛do it5 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 5)
java·vue
练习时长一年5 小时前
Spring配置类的演化
java·spring boot·spring