Skip to content

Java

什么是 JVM?有哪些主要职责?

JVM(Java Virtual Machine,Java 虚拟机)是一个抽象的计算机,它负责加载、验证、解释和执行 Java 字节码。主要职责包括:

  • 加载代码: 将编译好的 .class 文件加载到内存中。
  • 执行代码: 解释或即时编译(JIT)字节码,并在底层操作系统上运行。
  • 内存管理: 包括垃圾回收(GC)来自动回收无用对象,管理堆、方法区等。

这种设计使得 Java 具有平台无关性,只需编写一次代码,便能在不同平台上运行。

JDK、JRE 与 JVM 有什么区别?

  • JDK(Java Development Kit): 开发工具包,包含编译器(javac)、调试工具、文档生成器等,同时包含 JRE。
  • JRE(Java Runtime Environment): 运行环境,提供 JVM 以及 Java 核心类库,使得用户能够运行 Java 程序。
  • JVM: 是 JRE 的核心组件,负责执行 Java 字节码。

简单来说,JDK 用于开发,JRE 用于运行,而 JVM 则是真正执行代码的虚拟机。

什么是面向对象编程(OOP)?Java 如何支持 OOP?

面向对象编程是一种程序设计思想,它通过将数据和行为封装到对象中,来模拟现实世界中的事物。Java 通过以下机制支持 OOP:

  • 封装: 将数据(成员变量)和操作数据的方法封装在类中,保护数据安全。
  • 继承: 子类可以继承父类的属性和方法,实现代码复用。
  • 多态: 同一接口的不同实现可以有不同的行为,实现灵活性。
  • 抽象: 通过抽象类和接口定义模板和规范,不关注具体实现细节。

简述封装、继承、多态和抽象这四大特性

  • 封装: 隐藏对象内部实现细节,只暴露必要接口。例如,通过 private 访问修饰符保护类的内部数据。
  • 继承: 子类继承父类的属性和方法,减少重复代码。如:class Animal { }class Dog extends Animal { }
  • 多态: 同一个方法调用在不同对象上可能表现出不同行为。如:Animal a = new Dog(); a.sound(); 调用 Dog 类的 sound 方法。
  • 抽象: 定义抽象类或接口,只提供方法声明而不实现具体逻辑,由子类实现。例如:interface Shape { void draw(); }

什么是异常处理?如何使用 try-catch-finally?

异常处理用于捕获程序运行时可能出现的错误,并进行处理,防止程序崩溃。

  • try 块: 放置可能出现异常的代码。
  • catch 块: 捕获并处理 try 块中抛出的特定异常。可以有多个 catch 来分别处理不同异常。
  • finally 块: 无论是否发生异常,都会执行的代码(例如关闭资源)。

示例代码:

java
try {
    int result = 10 / 0;  // 可能抛出异常
} catch (ArithmeticException e) {
    System.out.println("除数不能为零!");
} finally {
    System.out.println("执行结束。");
}

Java 的集合框架及常见的集合类

集合框架提供了一系列用来存储和操作数据集合的类和接口。主要接口和实现类有:

  • List 接口: 有序且可重复。常用实现类:ArrayList、LinkedList。
  • Set 接口: 无序且不允许重复。常用实现类:HashSet、TreeSet。
  • Map 接口: 存储键值对,键不允许重复。常用实现类:HashMap、TreeMap。

这些集合类提供了丰富的方法来操作数据,如增加、删除、遍历等操作。

什么是 HashMap?它的基本原理是什么?

HashMap 是一种基于哈希表的数据结构,用来存储键值对。

  • 原理: 当存入一个键值对时,HashMap 通过键的 hashCode() 计算出一个哈希值,并映射到数组的某个索引位置;如果出现哈希冲突(多个键映射到同一索引),Java 8 以后会用链表或红黑树来存储多个元素。
  • 使用场景: 快速查找、插入和删除数据。

接口(interface)和抽象类(abstract class)的区别

  • 接口:
    • 只能声明常量和抽象方法(Java 8 后允许默认方法和静态方法)。
    • 一个类可以实现多个接口。
    • 主要用于定义行为规范,不涉及实现细节。
  • 抽象类:
    • 可以包含抽象方法和具体方法,也可以有成员变量。
    • 一个类只能继承一个抽象类。
    • 用于提供基本实现和模板,供子类扩展。

选择使用时:如果只需要定义行为而无共享实现,建议用接口;如果有部分实现需要共享,则使用抽象类。

什么是多线程?Java 中如何创建线程?

多线程是指程序同时运行多个线程,以充分利用 CPU 资源,实现并发处理。Java 中常用的创建线程方式有:

  • 继承 Thread 类: 重写 run() 方法,并调用 start() 启动线程。
    java
    class MyThread extends Thread {
        public void run() {
            System.out.println("线程运行中");
        }
    }
    // 启动线程
    new MyThread().start();
  • 实现 Runnable 接口: 实现 run() 方法,并将实例传入 Thread 对象,再调用 start()。
    java
    class MyRunnable implements Runnable {
        public void run() {
            System.out.println("线程运行中");
        }
    }
    // 启动线程
    new Thread(new MyRunnable()).start();

这种方式更灵活,因为 Java 支持多重继承接口,但只支持单继承类。

static 和 final 关键字的作用

  • static 关键字:

    • 用于声明类的成员变量或方法,使其归属于类本身,而不是对象。
    • 静态成员在内存中只有一份,所有对象共享。
    • 常用于工具类(如 Math 类中的方法)和常量定义。
  • final 关键字:

    • 修饰变量:表示常量,一旦赋值就不能改变。
    • 修饰方法:表示该方法不能被重写。
    • 修饰类:表示该类不能被继承。

这两个关键字有助于提高代码的安全性和稳定性。

Java 的垃圾回收机制(GC)

  • 原理:自动回收不再使用的对象内存,开发者无需手动释放。
  • 核心步骤
    1. 标记:找到所有存活对象。
    2. 清除:回收未标记的对象内存。
  • 常见垃圾回收器:G1、CMS(侧重低延迟)、Parallel GC(侧重吞吐量)。

==equals() 的区别

  • ==:比较对象内存地址是否相同(基本类型比较值)。
  • equals():默认比较地址,可重写(如 String 重写后比较内容)。
  • 示例
    java
    String a = new String("abc");
    String b = new String("abc");
    a == b;          // false(地址不同)
    a.equals(b);     // true(内容相同)

RESTful API 设计原则

  • 资源导向:URL 表示资源(如 /users)。
  • HTTP 方法:GET(查询)、POST(新增)、PUT(更新)、DELETE(删除)。
  • 状态码:200(成功)、404(资源不存在)、500(服务器错误)。
  • 数据格式:通常用 JSON 传输。

数据库连接池

  • 作用:预先创建并管理数据库连接,避免频繁创建/关闭连接。
  • 优势
    • 减少连接开销,提升性能。
    • 控制连接数,防止资源耗尽。
  • 常见实现:HikariCP(Spring Boot 默认)、Druid。

Released under the AGPL-3.0 License