每日 Java 面试题分享【第 19 天】

news/2025/2/3 12:51:52 标签: java, 开发语言, 面试

欢迎来到每日 Java 面试题分享栏目!
订阅专栏,不错过每一天的练习

今日分享 3 道面试题目!

评论区复述一遍印象更深刻噢~

目录

  • 问题一:Java Object 类中有什么方法,有什么作用?
  • 问题二:Java 中的字节码是什么?
  • 问题三:什么是 BIO、NIO、AIO?

问题一:Java Object 类中有什么方法,有什么作用?

Java Object 类的方法及作用

Object 类是 Java 所有类的祖先,位于 java.lang.Object,它为所有 Java 对象提供了一些基本的方法。


1. Object 类的主要方法

(1)equals(Object obj)—比较对象是否相等

作用:比较当前对象与参数对象是否 " 逻辑相等 "。

默认实现(在 Object 类中):

  • 使用 == 比较,即比较对象的内存地址,而不是内容。
  • 如果需要比较对象内容,需要重写 equals() 方法(如 StringInteger 等类已重写)。

示例:

java">class Person {
    String name;
    Person(String name) { this.name = name; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return name.equals(person.name);
    }
}

Person p1 = new Person("Alice");
Person p2 = new Person("Alice");
System.out.println(p1.equals(p2)); // true(重写后,比较内容)

(2)hashCode()—获取对象的哈希值

作用:返回对象的哈希码,用于哈希表(如 HashMapHashSet)存储对象时计算索引。

  • 默认实现:基于对象内存地址计算哈希值。
  • 通常与 equals() 一起重写,保证相等的对象哈希值相同(否则 HashSet 等容器可能无法正确存储)。

示例:

java">@Override
public int hashCode() {
    return name.hashCode();  // 让相同 name 的对象 hashCode 也相同
}

(3)toString()—返回对象的字符串表示

作用:返回对象的字符串描述,默认格式为 类名@哈希码

  • 建议重写,以便更清晰地输出对象信息。

示例:

java">class Person {
    String name;
    Person(String name) { this.name = name; }

    @Override
    public String toString() {
        return "Person{name='" + name + "'}";
    }
}

Person p = new Person("Alice");
System.out.println(p);  // Person{name='Alice'}

(4)getClass()—获取对象的 Class 对象

作用:返回对象的运行时 Class 对象,可以用于反射。

示例:

java">Person p = new Person("Alice");
System.out.println(p.getClass().getName());  // 输出类的全限定名

(5)clone()—复制对象

作用:返回对象的浅拷贝(仅拷贝基本类型,引用类型不会复制对象)。

  • 默认 Object 实现浅拷贝,必须实现 Cloneable 接口并重写 clone() 方法。

示例:

java">class Person implements Cloneable {
    String name;
    Person(String name) { this.name = name; }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Person p1 = new Person("Alice");
Person p2 = (Person) p1.clone();
System.out.println(p1 == p2);  // false,不是同一个对象

(6)finalize()—对象被回收前的操作

作用:对象被垃圾回收前执行的清理方法(通常不推荐使用)。

  • 被废弃(JDK 9 开始标记为 deprecated,可以用 try-with-resourcesclose() 代替。

示例:

java">@Override
protected void finalize() throws Throwable {
    System.out.println("对象即将被回收");
}

(7)wait() / notify() / notifyAll()—线程通信

这些方法用于线程同步,必须在同步代码块中调用。

  • wait():让当前线程进入等待状态,直到被 notify() 唤醒。
  • notify():随机唤醒一个等待的线程。
  • notifyAll():唤醒所有等待的线程。

示例:

java">synchronized (this) {
    this.wait();  // 让当前线程等待
    this.notify();  // 唤醒一个等待的线程
}

2. 总结

方法作用是否需要重写
equals(Object obj)比较对象是否相等(默认比较地址)通常需要
hashCode()计算对象哈希值(用于 HashMap)通常需要
toString()返回对象字符串信息通常需要
getClass()获取对象的 Class 信息一般不重写
clone()复制对象(默认浅拷贝)按需重写
finalize()对象回收前执行(已废弃)不建议使用
wait() / notify() / notifyAll()线程通信不可重写

重点

  1. equals()hashCode() 一起重写,确保 HashMap、HashSet 正常存储对象。
  2. toString() 适当重写,方便调试和日志输出。
  3. clone() 需要实现 Cloneable 接口,并自己实现深拷贝。
  4. finalize() 已过时,不推荐使用。
  5. wait() / notify() 用于线程同步,必须在 synchronized 代码块中调用。

这就是 Object 类的方法及其作用!


问题二:Java 中的字节码是什么?

Java 中的字节码(Bytecode)

1. 什么是字节码?

Java 字节码(Bytecode) 是一种 中间表示(Intermediate Representation,IR),它不是直接运行在 CPU 上的机器码,而是运行在 Java 虚拟机(JVM) 上的指令集。

当我们编写 Java 代码并编译(javac)后,Java 源代码(.java 文件)会被编译器转换成 字节码文件(.class 文件),然后由 JVM 解释或 JIT 编译后执行。


2. Java 字节码的特点
  • 平台无关性:Java 字节码可以在任何安装了 JVM 的环境中运行,而不需要重新编译。
  • 面向对象:字节码仍然保留了 Java 的对象模型,如类、方法、继承、接口等。
  • 堆栈指令集(Stack-based Instruction Set):JVM 采用基于操作数栈的架构(而非寄存器架构),所有操作通过入栈、出栈完成。

3. 字节码执行流程
  1. 编译:Java 源代码(.java)→ 编译器(javac → 字节码(.class
  2. 加载:JVM 通过类加载器(ClassLoader) 加载 .class 文件到方法区。
  3. 解释或编译
    • 解释执行:字节码由 解释器(Interpreter) 逐条翻译成机器码并执行(启动快但慢)。
    • JIT(即时编译,Just-In-Time Compiler):JVM 可能将热点代码转换为机器码,提高执行效率。

4. Java 字节码示例

例如,编译以下代码:

java">public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Bytecode!");
    }
}

使用 javap -c HelloWorld.class 反编译:

public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2 // 获取 System.out
       3: ldc           #3 // 加载字符串 "Hello, Bytecode!"
       5: invokevirtual #4 // 调用 println 方法
       8: return
  • getstatic:获取 System.out
  • ldc:加载字符串常量
  • invokevirtual:调用 println() 方法

5. 字节码优化

JVM 使用 JIT(Just-In-Time 编译)垃圾回收(GC) 进行优化:

  • 热点代码 会被 JIT 编译成机器码,提高运行效率。
  • 死代码消除、方法内联 等优化提升性能。

6. 总结
特点说明
平台无关编译后可运行在任意 JVM 上
基于栈架构通过栈操作指令执行计算
JIT 编译优化热点代码会被 JIT 转换为机器码,提高性能
面向对象支持类、方法、继承等

Java 字节码是 Java 跨平台特性的关键,也是 JVM 执行 Java 代码的中间步骤!🚀


问题三:什么是 BIO、NIO、AIO?

BIO、NIO、AIO 的概念与区别

在 Java 中,BIO(Blocking I/O)、NIO(Non-blocking I/O)、AIO(Asynchronous I/O) 是三种不同的 I/O(输入/输出)模型,主要用于网络编程文件操作。它们的核心区别在于 数据读写时的阻塞行为线程管理方式


1. BIO(Blocking I/O)—阻塞式 I/O

概念

  • 同步 & 阻塞:每个连接都需要一个独立的线程处理,数据读取/写入时会阻塞,直到操作完成。
  • 适用于小规模连接(如传统 C/S 架构),如 Web 服务器、数据库连接等。
  • 缺点
    • 线程资源消耗大,每个连接都需要一个线程,连接数过多时,系统负担重。
    • 低并发,大量连接时,线程切换成本高,容易导致 " 线程过载 "

示例

java">ServerSocket server = new ServerSocket(8080);
while (true) {
    Socket socket = server.accept(); // 阻塞等待连接
    new Thread(() -> {
        try {
            InputStream in = socket.getInputStream();
            byte[] buffer = new byte[1024];
            int len = in.read(buffer); // 阻塞等待数据
            System.out.println(new String(buffer, 0, len));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }).start();
}
  • server.accept() 阻塞等待客户端连接。
  • in.read(buffer) 阻塞等待数据到来。
  • 每个请求都创建新线程,连接数多时消耗大。

2. NIO(Non-blocking I/O)—非阻塞式 I/O

概念

  • 同步 & 非阻塞:采用 多路复用(Selector) 机制,一个线程可以管理多个连接,提升并发性能。
  • 适用于高并发场景(如聊天系统、游戏服务器)
  • 特点
    • 非阻塞,但仍是同步 I/O(线程需要主动轮询检查数据)。
    • 采用 Selector 监听多个 Channel,避免一个线程对应一个连接的弊端。

示例

java">Selector selector = Selector.open();
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false); // 设置非阻塞模式
serverChannel.bind(new InetSocketAddress(8080));
serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 监听连接事件

while (true) {
    selector.select(); // 轮询监听事件(阻塞)
    Set<SelectionKey> keys = selector.selectedKeys();
    for (SelectionKey key : keys) {
        if (key.isAcceptable()) { // 处理新连接
            SocketChannel socketChannel = serverChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (key.isReadable()) { // 处理可读数据
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            channel.read(buffer);
            System.out.println(new String(buffer.array()));
        }
    }
    keys.clear();
}
  • Selector 监听多个 Channel,避免多个线程处理多个连接。
  • 数据读取非阻塞,如果没有数据,不会卡住线程。
  • 适用于高并发服务器(如 Netty)

3. AIO(Asynchronous I/O)— 异步 I/O

概念

  • 异步 & 非阻塞:基于 操作系统内核 异步通知机制,I/O 操作完成后会回调相应的处理逻辑,不需要手动轮询检查。
  • 适用于超高并发(如高吞吐量服务器、消息推送)
  • 特点
    • 真正的异步,数据准备好后,操作系统会自动回调处理数据,避免轮询。
    • 比 NIO 更高效,但依赖于操作系统的异步 I/O 支持(Windows、Linux 支持良好)。

示例

java">AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open()
    .bind(new InetSocketAddress(8080));

server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
    @Override
    public void completed(AsynchronousSocketChannel channel, Void attachment) {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        channel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {
            @Override
            public void completed(Integer result, ByteBuffer buffer) {
                buffer.flip();
                System.out.println(new String(buffer.array()));
            }
            @Override
            public void failed(Throwable exc, ByteBuffer attachment) {
                exc.printStackTrace();
            }
        });
    }
    @Override
    public void failed(Throwable exc, Void attachment) {
        exc.printStackTrace();
    }
});
  • server.accept() 是非阻塞的,连接建立后自动执行回调 completed()
  • channel.read() 也是异步的,数据到达后触发 completed(),无需轮询检查。
  • 适用于超高并发,如 Netty 也有 AIO 支持。

4. BIO、NIO、AIO 区别总结

特性BIO(同步阻塞)NIO(同步非阻塞)AIO(异步非阻塞)
线程模型一个连接占用一个线程一个线程管理多个连接真正的异步,I/O 完成后回调
阻塞方式阻塞(线程等待)非阻塞(轮询检查)非阻塞(OS 直接回调)
并发能力低(线程数多时资源耗尽)中等(Selector 机制)高(事件驱动,线程数少)
适用场景小规模连接(如传统 Web)高并发(如聊天室、消息推送)超高并发(如 Netty、分布式系统)
JDK 支持JDK 1.0JDK 1.4(java.nioJDK 1.7(java.nio.channels

5. 何时使用 BIO、NIO、AIO?

  1. BIO

    • 适用于连接数较少并发要求不高的应用(如 Web 服务器、小型服务端)。
    • 优点:实现简单,调试方便。
    • 缺点:高并发下资源消耗大,性能低
  2. NIO

    • 适用于高并发场景,如聊天室、游戏服务器、即时通讯
    • 优点:支持单线程管理多个连接,性能比 BIO 高。
    • 缺点:代码复杂度增加,需要手动管理 SelectorChannel
  3. AIO

    • 适用于超高并发,如Netty、分布式架构、消息推送
    • 优点:完全异步,系统资源占用少,适合高吞吐场景。
    • 缺点:依赖操作系统支持,适用范围比 NIO 更局限。

如果是高并发网络编程,推荐使用 Netty(基于 NIO 和 AIO 的封装),性能更强!🚀


总结

今天的 3 道 Java 面试题,您是否掌握了呢?持续关注我们的每日分享,深入学习 Java 面试的各个细节,快速提升技术能力!如果有任何疑问,欢迎在评论区留言,我们会第一时间解答!

明天见!🎉


http://www.niftyadmin.cn/n/5840819.html

相关文章

Rust 控制流语法详解

Rust 控制流语法详解 控制流是编程语言中用于控制代码执行顺序的重要机制。Rust 提供了多种控制流语法&#xff0c;包括条件判断&#xff08;if、else if&#xff09;、循环&#xff08;loop、while、for&#xff09;等。本文将详细介绍这些语法&#xff0c;并通过示例展示它们…

ARM嵌入式学习--第十二天(WDOG,RTC)

--WDOG -介绍 WatchDog是为了能够防止程序跑飞而使用的一种硬件模块&#xff0c;如果你的程序没有跑飞&#xff0c;那么你的程序会定时的去喂看门狗&#xff1b;如果你的程序跑飞了&#xff0c;那么就不会再去喂狗了&#xff0c;如果超过了喂狗时间&#xff0c;那么狗就会自己…

人工智能学习(四)之机器学习基本概念

机器学习基本概念详细解析&#xff1a;从生活实例轻松入门 在当今数字化时代&#xff0c;机器学习作为人工智能领域的核心技术之一&#xff0c;正深刻地改变着我们的生活和工作方式。从智能语音助手到图像识别系统&#xff0c;从个性化推荐引擎到自动驾驶汽车&#xff0c;机器…

C++进阶: 红黑树及map与set封装

红黑树总结整理 红黑色概述&#xff1a; 红黑树整理与AVL树类似&#xff0c;但在对树的平衡做控制时&#xff0c;AVL树会比红黑树更严格。 AVL树是通过引入平衡因子的概念进行对树高度控制。 红黑树则是对每个节点标记颜色&#xff0c;对颜色进行控制。 红黑树控制规则&…

使用朴素贝叶斯对散点数据进行分类

本文将通过一个具体的例子&#xff0c;展示如何使用 Python 和 scikit-learn 库中的 GaussianNB 模型&#xff0c;对二维散点数据进行分类&#xff0c;并可视化分类结果。 1. 数据准备 假设我们有两个类别的二维散点数据&#xff0c;每个类别包含若干个点。我们将这些点分别存…

[LeetCode]day10 707.设计链表

707. 设计链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果…

冲刺一区!挑战7天完成一篇趋势性分析GBD DAY1-7

Day1. 公开数据库的挖掘太火热了,其中GBD数据库的挖掘又十分的火爆.那我就来挑战一篇GBD、一篇关于趋势性分析的GBD&#xff01; GBD数据库挖掘是目前的四大刊常客&#xff0c;经常出现在顶级期刊上面。这个数据库亮点就是&#xff1a;可视化&#xff0c;统计学简单、而数据可…

Spring Boot 实例解析:HelloWorld 探究

POM 文件剖析&#xff1a; 父项目&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring‐boot‐starter‐parent</artifactId><version>1.5.9.RELEASE</version> </parent> 他的父项目是 <…