2025 年 Java 校招 120 道含实操面试题目及答案完整合集_java校招笔试题目
Java校招120道面试题目合集及答案(含实操)
一、Java基础
1. Java语言有哪些特点?
答案:Java具有简单性、面向对象、平台无关性等特点。
实操:创建一个简单的Java程序,演示面向对象的封装特性。
// 定义一个学生类,封装姓名和年龄属性class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } // 提供公共的访问方法 public String getName() { return name; } public int getAge() { return age; }}public class Main { public static void main(String[] args) { Student student = new Student(\"张三\", 20); System.out.println(student.getName() + \" 年龄: \" + student.getAge()); }}
2. 什么是Java虚拟机(JVM)?
答案:JVM是执行字节码的虚拟计算机,实现了“一次编写,到处运行”。
实操:使用javap
命令查看字节码。
# 编译Java文件javac Main.java# 查看字节码javap -c Main
3. \"static\"关键字的作用?
答案:static修饰的成员属于类,而非实例。
实操:创建静态工具类计算圆的面积。
public class MathUtils { // 静态常量 public static final double PI = 3.14159; // 静态方法 public static double calculateArea(double radius) { return PI * radius * radius; }}// 使用静态成员double area = MathUtils.calculateArea(5.0);
4. Java支持的数据类型有哪些?
答案:基本数据类型和引用数据类型。
实操:演示自动装箱与拆箱。
Integer numObj = 10; // 自动装箱int num = numObj; // 自动拆箱System.out.println(num + 5); // 输出15
5. 方法覆盖(Overriding)与重载(Overload)的区别?
答案:覆盖发生在父子类,重载在同一类中。
实操:实现方法覆盖与重载。
class Animal { public void makeSound() { System.out.println(\"动物发出声音\"); }}class Dog extends Animal { @Override public void makeSound() { // 方法覆盖 System.out.println(\"汪汪汪\"); } public void makeSound(int times) { // 方法重载 for (int i = 0; i < times; i++) { System.out.print(\"汪 \"); } }}
6. 什么是构造方法?
答案:构造方法用于初始化对象。
实操:创建带参数的构造方法。
class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getInfo() { return name + \",年龄:\" + age; }}Person p = new Person(\"李四\", 25);System.out.println(p.getInfo());
7. Java支持多继承吗?
答案:Java类不支持多继承,但接口可以多实现。
实操:实现多接口。
interface Flyable { void fly();}interface Swimmable { void swim();}class Duck implements Flyable, Swimmable { @Override public void fly() { System.out.println(\"鸭子飞\"); } @Override public void swim() { System.out.println(\"鸭子游\"); }}
8. 值传递与引用传递的区别?
答案:Java中基本类型是值传递,对象是引用传递。
实操:验证引用传递。
class Point { int x, y; public Point(int x, int y) { this.x = x; this.y = y; }}public class Main { public static void main(String[] args) { Point p = new Point(10, 20); modify(p); System.out.println(\"x=\" + p.x + \", y=\" + p.y); // 输出x=100, y=200 } public static void modify(Point pt) { pt.x = 100; pt.y = 200; }}
9. 进程与线程的区别?
答案:进程是资源分配单位,线程是执行单元。
实操:使用jconsole
监控Java进程与线程。
# 启动示例程序java -cp . Main# 启动监控工具jconsole
10. 创建线程的方式有哪些?
答案:继承Thread类、实现Runnable接口等。
实操:使用ExecutorService创建线程池。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(3); for (int i = 0; i < 5; i++) { final int taskId = i; executor.submit(() -> { System.out.println(\"执行任务: \" + taskId + \",线程: \" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); }}
二、多线程与并发
11. 如何实现线程同步?
答案:使用synchronized
关键字或ReentrantLock
。
实操:使用synchronized
实现线程安全的计数器。
class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; }}
12. 什么是线程安全?
答案:多个线程访问共享资源时不会导致数据不一致。
实操:对比ArrayList
与Vector
的线程安全性。
import java.util.ArrayList;import java.util.List;import java.util.Vector;public class ThreadSafetyDemo { public static void main(String[] args) throws InterruptedException { // 使用非线程安全的ArrayList List<Integer> arrayList = new ArrayList<>(); // 使用线程安全的Vector List<Integer> vector = new Vector<>(); // 启动多个线程添加元素 Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { arrayList.add(i); vector.add(i); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { arrayList.add(i); vector.add(i); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(\"ArrayList size: \" + arrayList.size()); // 可能小于2000 System.out.println(\"Vector size: \" + vector.size()); // 总是2000 }}
13. 解释Java中的锁机制
答案:Java提供synchronized
和Lock
接口实现锁机制。
实操:使用ReentrantLock
实现可重入锁。
import java.util.concurrent.locks.ReentrantLock;class Resource { private final ReentrantLock lock = new ReentrantLock(); public void accessResource() { lock.lock(); try { // 执行临界区代码 System.out.println(Thread.currentThread().getName() + \" 获取锁\"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(Thread.currentThread().getName() + \" 释放锁\"); } }}
14. 什么是死锁?如何避免?
答案:死锁是两个或多个线程互相等待对方释放资源的情况。
实操:模拟死锁并分析。
public class DeadlockDemo { private static final Object lock1 = new Object(); private static final Object lock2 = new Object(); public static void main(String[] args) { Thread t1 = new Thread(() -> { synchronized (lock1) { System.out.println(\"线程1获取锁1\"); try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (lock2) { System.out.println(\"线程1获取锁2\"); } } }); Thread t2 = new Thread(() -> { synchronized (lock2) { System.out.println(\"线程2获取锁2\"); try { Thread.sleep(100); } catch (InterruptedException e) {} synchronized (lock1) { System.out.println(\"线程2获取锁1\"); } } }); t1.start(); t2.start(); }}
15. 什么是volatile关键字?
答案:保证变量的可见性,禁止指令重排序。
实操:使用volatile实现线程间通信。
public class VolatileDemo { private static volatile boolean flag = false; public static void main(String[] args) { new Thread(() -> { while (!flag) { // 等待flag变为true } System.out.println(\"线程收到通知,flag已变为true\"); }).start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } flag = true; System.out.println(\"主线程已设置flag为true\"); }}
16. 解释Java中的wait()和notify()方法
答案:用于线程间的协作,必须在synchronized
块中调用。
实操:使用生产者-消费者模型演示。
class SharedResource { private int data; private boolean available = false; public synchronized void produce(int value) { while (available) { try { wait(); } catch (InterruptedException e) {} } data = value; available = true; notifyAll(); } public synchronized int consume() { while (!available) { try { wait(); } catch (InterruptedException e) {} } available = false; notifyAll(); return data; }}
17. 什么是线程池?如何创建?
答案:线程池管理线程的创建和复用,提高性能。
实操:使用Executors
工厂类创建不同类型的线程池。
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class ThreadPoolDemo { public static void main(String[] args) { // 创建固定大小的线程池 ExecutorService fixedPool = Executors.newFixedThreadPool(5); // 创建缓存线程池 ExecutorService cachedPool = Executors.newCachedThreadPool(); // 创建单线程池 ExecutorService singlePool = Executors.newSingleThreadExecutor(); // 执行任务 fixedPool.submit(() -> System.out.println(\"任务执行\")); // 关闭线程池 fixedPool.shutdown(); }}
18. 解释Callable和Future接口
答案:Callable有返回值,Future用于获取异步结果。
实操:使用Callable和Future实现异步计算。
import java.util.concurrent.*;public class CallableFutureDemo { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executor = Executors.newSingleThreadExecutor(); Callable<Integer> task = () -> { Thread.sleep(2000); return 100; }; Future<Integer> future = executor.submit(task); System.out.println(\"等待结果...\"); System.out.println(\"结果: \" + future.get()); executor.shutdown(); }}
19. 什么是原子操作?
答案:不可中断的操作,Java提供了Atomic
类实现原子操作。
实操:使用AtomicInteger
实现无锁计数器。
import java.util.concurrent.atomic.AtomicInteger;public class AtomicDemo { private static AtomicInteger counter = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.incrementAndGet(); } }); Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) { counter.incrementAndGet(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(\"计数器值: \" + counter.get()); // 输出2000 }}
20. 什么是并发集合?
答案:线程安全的集合,如ConcurrentHashMap
、CopyOnWriteArrayList
等。
实操:使用ConcurrentHashMap
统计单词频率。
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentCollectionDemo { public static void main(String[] args) { ConcurrentHashMap<String, Integer> wordCount = new ConcurrentHashMap<>(); String[] words = {\"apple\", \"banana\", \"apple\", \"cherry\", \"banana\"}; for (String word : words) { wordCount.compute(word, (k, v) -> (v == null) ? 1 : v + 1); } System.out.println(wordCount); // 输出 {apple=2, banana=2, cherry=1} }}
三、集合框架
21. Java集合框架的主要接口有哪些?
答案:主要接口包括Collection
、List
、Set
、Map
等。
实操:创建不同类型的集合。
import java.util.*;public class CollectionFrameworkDemo { public static void main(String[] args) { // List示例 List<String> list = new ArrayList<>(); list.add(\"A\"); list.add(\"B\"); list.add(\"C\"); // Set示例 Set<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(2); // 重复元素,不会被添加 // Map示例 Map<String, Integer> map = new HashMap<>(); map.put(\"one\", 1); map.put(\"two\", 2); }}
22. ArrayList和LinkedList的区别是什么?
答案:ArrayList基于数组,LinkedList基于链表。
实操:对比两种列表的插入性能。
import java.util.ArrayList;import java.util.LinkedList;import java.util.List;public class ListPerformanceDemo { public static void main(String[] args) { int size = 100000; // 测试ArrayList插入性能 List<Integer> arrayList = new ArrayList<>(); long startTime = System.currentTimeMillis(); for (int i = 0; i < size; i++) { arrayList.add(0, i); // 在头部插入 } long endTime = System.currentTimeMillis(); System.out.println(\"ArrayList插入时间: \" + (endTime - startTime) + \"ms\"); // 测试LinkedList插入性能 List<Integer> linkedList = new LinkedList<>(); startTime = System.currentTimeMillis(); for (int i = 0; i < size; i++) { linkedList.add(0, i); // 在头部插入 } endTime = System.currentTimeMillis(); System.out.println(\"LinkedList插入时间: \" + (endTime - startTime) + \"ms\"); }}
23. HashMap和Hashtable的区别是什么?
答案:HashMap非线程安全,Hashtable线程安全。
实操:对比HashMap和Hashtable的使用。
import java.util.HashMap;import java.util.Hashtable;import java.util.Map;public class MapDifferenceDemo { public static void main(String[] args) { // HashMap允许null键和null值 Map<String, String> hashMap = new HashMap<>(); hashMap.put(null, \"value\"); hashMap.put(\"key\", null); // Hashtable不允许null键和null值 Map<String, String> hashtable = new Hashtable<>(); // hashtable.put(null, \"value\"); // 抛出NullPointerException // hashtable.put(\"key\", null); // 抛出NullPointerException }}
24. 如何实现集合的排序?
答案:使用Collections.sort()
或Stream.sorted()
。
实操:对自定义对象列表进行排序。
import java.util.ArrayList;import java.util.Collections;import java.util.List;class Student implements Comparable<Student> { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } @Override public int compareTo(Student other) { return Integer.compare(this.score, other.score); } @Override public String toString() { return name + \": \" + score; }}public class SortingDemo { public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student(\"张三\", 85)); students.add(new Student(\"李四\", 72)); students.add(new Student(\"王五\", 90)); Collections.sort(students); System.out.println(students); // 按分数升序排列 }}
25. 什么是迭代器(Iterator)?
答案:用于遍历集合的接口,支持元素的删除操作。
实操:使用迭代器遍历并删除元素。
import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class IteratorDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add(\"A\"); list.add(\"B\"); list.add(\"C\"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); if (element.equals(\"B\")) { iterator.remove(); // 安全删除元素 } } System.out.println(list); // 输出 [A, C] }}
26. 什么是Java 8的Stream API?
答案:用于处理集合的流式操作,支持过滤、映射、聚合等。
实操:使用Stream API进行数据处理。
import java.util.Arrays;import java.util.List;import java.util.stream.Collectors;public class StreamDemo { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // 过滤偶数并计算平方和 int sum = numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * n) .reduce(0, Integer::sum); System.out.println(\"偶数的平方和: \" + sum); // 输出 220 }}
27. 什么是TreeMap和TreeSet?
答案:基于红黑树实现,元素按自然顺序或指定比较器排序。
实操:使用TreeSet存储自定义对象。
import java.util.TreeSet;class Person implements Comparable<Person> { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Person other) { return Integer.compare(this.age, other.age); } @Override public String toString() { return name + \": \" + age; }}public class TreeSetDemo { public static void main(String[] args) { TreeSet<Person> people = new TreeSet<>(); people.add(new Person(\"张三\", 25)); people.add(new Person(\"李四\", 20)); people.add(new Person(\"王五\", 30)); System.out.println(people); // 按年龄升序排列 }}
28. 什么是CopyOnWriteArrayList?
答案:写时复制的线程安全列表,适用于读多写少的场景。
实操:多线程环境下使用CopyOnWriteArrayList。
import java.util.List;import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteArrayListDemo { public static void main(String[] args) { List<String> list = new CopyOnWriteArrayList<>(); // 线程1添加元素 Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { list.add(\"元素\" + i); } }); // 线程2遍历元素 Thread t2 = new Thread(() -> { for (String element : list) { System.out.println(element); } }); t1.start(); t2.start(); }}
29. 什么是LinkedHashMap?
答案:维护插入顺序或访问顺序的HashMap。
实操:使用LinkedHashMap实现LRU缓存。
import java.util.LinkedHashMap;import java.util.Map;public class LRUCacheDemo extends LinkedHashMap<Integer, Integer> { private final int capacity; public LRUCacheDemo(int capacity) { super(capacity, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) { return size() > capacity; } }; this.capacity = capacity; } public static void main(String[] args) { LRUCacheDemo cache = new LRUCacheDemo(3); cache.put(1, 1); cache.put(2, 2); cache.put(3, 3); cache.get(1); // 访问元素1,使其变为最近使用 cache.put(4, 4); // 超出容量,移除最久未使用的元素2 System.out.println(cache); // 输出 {3=3, 1=1, 4=4} }}
30. 如何遍历Map?
答案:可以使用keySet()、entrySet()或forEach()方法。
实操:演示三种遍历Map的方式。
import java.util.HashMap;import java.util.Map;public class MapTraversalDemo { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put(\"A\", 1); map.put(\"B\", 2); map.put(\"C\", 3); // 方式1:使用keySet() for (String key : map.keySet()) { System.out.println(key + \" : \" + map.get(key)); } // 方式2:使用entrySet() for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + \" : \" + entry.getValue()); } // 方式3:使用forEach() map.forEach((key, value) -> System.out.println(key + \" : \" + value)); }}
四、异常处理
31. Java异常处理机制是什么?
答案:通过try-catch-finally和throws关键字实现。
实操:捕获并处理异常。
public class ExceptionHandlingDemo { public static void main(String[] args) { try { int result = divide(10, 0); System.out.println(\"结果: \" + result); } catch (ArithmeticException e) { System.out.println(\"捕获到异常: \" + e.getMessage()); } finally { System.out.println(\"执行finally块\"); } } public static int divide(int a, int b) { return a / b; // 会抛出ArithmeticException }}
32. 检查型异常(Checked Exception)和非检查型异常(Unchecked Exception)的区别是什么?
答案:检查型异常必须被捕获或声明抛出,非检查型异常不强制。
实操:演示两种异常的区别。
import java.io.FileInputStream;import java.io.IOException;public class ExceptionTypeDemo { public static void main(String[] args) { // 检查型异常,必须处理 try { FileInputStream fis = new FileInputStream(\"file.txt\"); } catch (IOException e) { e.printStackTrace(); } // 非检查型异常,不强制处理 int[] arr = new int[5]; System.out.println(arr[10]); // 抛出ArrayIndexOutOfBoundsException }}
33. throw和throws的区别是什么?
答案:throw用于手动抛出异常,throws用于声明方法可能抛出的异常。
实操:自定义异常并使用throw和throws。
class CustomException extends Exception { public CustomException(String message) { super(message); }}public class ThrowThrowsDemo { public static void main(String[] args) { try { validateAge(-5); } catch (CustomException e) { System.out.println(e.getMessage()); } } public static void validateAge(int age) throws CustomException { if (age < 0) { throw new CustomException(\"年龄不能为负数\"); } }}
34. 什么是finally块?
答案:无论是否发生异常,finally块中的代码总会执行。
实操:演示finally块的执行。
public class FinallyDemo { public static void main(String[] args) { try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println(\"捕获到除零异常\"); } finally { System.out.println(\"执行finally块\"); } }}
35. 什么是自定义异常?
答案:用户自定义的异常类,继承自Exception或其子类。
实操:创建自定义异常类。
class InvalidEmailException extends Exception { public InvalidEmailException(String message) { super(message); }}public class CustomExceptionDemo { public static void main(String[] args) { try { validateEmail(\"invalid_email\"); } catch (InvalidEmailException e) { System.out.println(e.getMessage()); } } public static void validateEmail(String email) throws InvalidEmailException { if (!email.contains(\"@\")) { throw new InvalidEmailException(\"无效的邮箱地址\"); } }}
36. 什么是try-with-resources语句?
答案:自动关闭实现了AutoCloseable接口的资源。
实操:使用try-with-resources读取文件。
import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class TryWithResourcesDemo { public static void main(String[] args) { try (BufferedReader br = new BufferedReader(new FileReader(\"file.txt\"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } }}
37. 什么是异常链(Exception Chaining)?
答案:将一个异常包装在另一个异常中,保留原始异常信息。
实操:实现异常链。
class DatabaseException extends Exception { public DatabaseException(String message, Throwable cause) { super(message, cause); }}public class ExceptionChainingDemo { public static void main(String[] args) { try { connectToDatabase(); } catch (DatabaseException e) { System.out.println(\"数据库连接失败: \" + e.getMessage()); System.out.println(\"原始异常: \" + e.getCause()); } } public static void connectToDatabase() throws DatabaseException { try { // 模拟数据库连接失败 throw new RuntimeException(\"连接超时\"); } catch (RuntimeException e) { throw new DatabaseException(\"无法连接数据库\", e); } }}
38. 如何自定义异常处理机制?
答案:通过实现Thread.UncaughtExceptionHandler接口。
实操:设置全局异常处理器。
public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(\"线程 \" + t.getName() + \" 抛出异常: \" + e.getMessage()); // 可以添加日志记录或其他处理逻辑 } public static void main(String[] args) { Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler()); Thread t = new Thread(() -> { throw new RuntimeException(\"测试异常\"); }); t.start(); }}
39. 什么是断言(Assertion)?
答案:用于调试的机制,验证程序中的假设。
实操:使用断言检查参数。
public class AssertionDemo { public static void main(String[] args) { int age = -5; assert age >= 0 : \"年龄不能为负数\"; System.out.println(\"年龄: \" + age); }}// 启用断言运行程序// java -ea AssertionDemo
40. 解释Java中的错误(Error)和异常(Exception)的区别
答案:Error表示系统级错误,无法恢复;Exception表示可处理的异常情况。
实操:演示StackOverflowError。
public class ErrorDemo { public static void main(String[] args) { recursiveMethod(); } public static void recursiveMethod() { recursiveMethod(); // 无限递归,会导致StackOverflowError }}
五、IO与NIO
41. Java中有几种类型的流?
答案:字节流和字符流,分别对应InputStream/OutputStream和Reader/Writer。
实操:使用字节流复制文件。
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream(\"input.txt\"); FileOutputStream fos = new FileOutputStream(\"output.txt\")) { int byteRead; while ((byteRead = fis.read()) != -1) { fos.write(byteRead); } } catch (IOException e) { e.printStackTrace(); } }}
42. 什么是Java NIO?
答案:非阻塞IO,基于通道(Channel)和缓冲区(Buffer)。
实操:使用NIO复制文件。
import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class NioDemo { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream(\"input.txt\"); FileOutputStream fos = new FileOutputStream(\"output.txt\"); FileChannel inChannel = fis.getChannel(); FileChannel outChannel = fos.getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(1024); while (inChannel.read(buffer) != -1) { buffer.flip(); outChannel.write(buffer); buffer.clear(); } } catch (IOException e) { e.printStackTrace(); } }}
43. 什么是缓冲区(Buffer)?
答案:NIO中用于存储数据的对象,有position、limit和capacity属性。
实操:使用ByteBuffer读写数据。
import java.nio.ByteBuffer;public class BufferDemo { public static void main(String[] args) { ByteBuffer buffer = ByteBuffer.allocate(10); // 写入数据 buffer.put((byte) \'A\'); buffer.put((byte) \'B\'); buffer.put((byte) \'C\'); // 切换到读模式 buffer.flip(); // 读取数据 while (buffer.hasRemaining()) { System.out.print((char) buffer.get() + \" \"); } // 清空缓冲区 buffer.clear(); }}
44. 什么是通道(Channel)?
答案:NIO中用于与数据源交互的双向通道。
实操:使用FileChannel读取文件。
import java.io.FileInputStream;import java.io.IOException;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class ChannelDemo { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream(\"input.txt\"); FileChannel channel = fis.getChannel()) { ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = channel.read(buffer); while (bytesRead != -1) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = channel.read(buffer); } } catch (IOException e) { e.printStackTrace(); } }}
45. 什么是Selector?
答案:NIO中用于多路复用的选择器,可监控多个通道的IO事件。
实操:简单的Selector示例。
import java.io.IOException;import java.net.InetSocketAddress;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.util.Iterator;import java.util.Set;public class SelectorDemo { public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.socket().bind(new InetSocketAddress(8080)); serverChannel.configureBlocking(false); serverChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); if (readyChannels == 0) continue; Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { // 处理连接事件 } else if (key.isReadable()) { // 处理读取事件 } keyIterator.remove(); } } }}
46. 什么是字符流和字节流?
答案:字节流处理原始字节,字符流处理字符数据。
实操:使用字符流写入文件。
import java.io.FileWriter;import java.io.IOException;public class CharacterStreamDemo { public static void main(String[] args) { try (FileWriter writer = new FileWriter(\"output.txt\")) { writer.write(\"Hello, World!\\n\"); writer.write(\"这是一个字符流示例。\"); } catch (IOException e) { e.printStackTrace(); } }}
47. 什么是序列化和反序列化?
答案:将对象转换为字节流和从字节流恢复对象的过程。
实操:实现对象的序列化和反序列化。
import java.io.*;class Person implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name + \", \" + age + \"岁\"; }}public class SerializationDemo { public static void main(String[] args) { // 序列化 try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(\"person.ser\"))) { Person person = new Person(\"张三\", 25); oos.writeObject(person); } catch (IOException e) { e.printStackTrace(); } // 反序列化 try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(\"person.ser\"))) { Person restoredPerson = (Person) ois.readObject(); System.out.println(restoredPerson); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } }}
48. 如何实现自定义序列化?
答案:通过实现writeObject()和readObject()方法。
实操:自定义序列化示例。
import java.io.*;class CustomSerializable implements Serializable { private static final long serialVersionUID = 1L; private int value; public CustomSerializable(int value) { this.value = value; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeInt(value * 2); // 自定义序列化逻辑 } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); value = in.readInt() / 2; // 自定义反序列化逻辑 } public int getValue() { return value; }}
49. 什么是Java中的文件过滤器?
答案:用于过滤文件的接口,实现FilenameFilter或FileFilter。
实操:使用文件过滤器列出所有txt文件。
import java.io.File;import java.io.FilenameFilter;public class FileFilterDemo { public static void main(String[] args) { File dir = new File(\".\"); FilenameFilter filter = (dir1, name) -> name.endsWith(\".txt\"); File[] txtFiles = dir.listFiles(filter); if (txtFiles != null) { for (File file : txtFiles) { System.out.println(file.getName()); } } }}
50. 如何实现文件加密和解密?
答案:使用Java Cryptography Architecture (JCA)。
实操:使用AES加密文件。
import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import java.io.*;import java.security.NoSuchAlgorithmException;public class FileEncryptionDemo { public static void main(String[] args) throws Exception { // 生成密钥 SecretKey secretKey = KeyGenerator.getInstance(\"AES\").generateKey(); // 加密文件 encryptFile(\"plain.txt\", \"encrypted.bin\", secretKey); // 解密文件 decryptFile(\"encrypted.bin\", \"decrypted.txt\", secretKey); } public static void encryptFile(String inputFile, String outputFile, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance(\"AES\"); cipher.init(Cipher.ENCRYPT_MODE, key); try (FileInputStream fis = new FileInputStream(inputFile); FileOutputStream fos = new FileOutputStream(outputFile); CipherOutputStream cos = new CipherOutputStream(fos, cipher)) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { cos.write(buffer, 0, bytesRead); } } } public static void decryptFile(String inputFile, String outputFile, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance(\"AES\"); cipher.init(Cipher.DECRYPT_MODE, key); try (FileInputStream fis = new FileInputStream(inputFile); CipherInputStream cis = new CipherInputStream(fis, cipher); FileOutputStream fos = new FileOutputStream(outputFile)) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = cis.read(buffer)) != -1) { fos.write(buffer, 0, bytesRead); } } }}
六、反射与注解
51. 什么是Java反射?
答案:运行时动态获取类的信息并操作类的机制。
实操:使用反射创建对象并调用方法。
import java.lang.reflect.Constructor;import java.lang.reflect.Method;class MyClass { private String message; public MyClass(String message) { this.message = message; } public void printMessage() { System.out.println(\"Message: \" + message); }}public class ReflectionDemo { public static void main(String[] args) throws Exception { // 获取Class对象 Class<?> clazz = Class.forName(\"MyClass\"); // 创建对象 Constructor<?> constructor = clazz.getConstructor(String.class); Object obj = constructor.newInstance(\"Hello, Reflection!\"); // 调用方法 Method method = clazz.getMethod(\"printMessage\"); method.invoke(obj); }}
52. 如何获取Class对象?
答案:三种方式:Class.forName()
、类名.class
、对象.getClass()
。
实操:演示三种获取Class对象的方式。
public class GetClassDemo { public static void main(String[] args) throws ClassNotFoundException { // 方式1:使用Class.forName() Class<?> clazz1 = Class.forName(\"java.util.ArrayList\"); // 方式2:使用类名.class Class<?> clazz2 = ArrayList.class; // 方式3:使用对象.getClass() ArrayList<String> list = new ArrayList<>(); Class<?> clazz3 = list.getClass(); System.out.println(clazz1 == clazz2); // 输出true System.out.println(clazz2 == clazz3); // 输出true }}
53. 什么是Java注解?
答案:为程序元素(类、方法等)添加元数据的机制。
实操:定义和使用自定义注解。
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;// 定义注解@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@interface MyAnnotation { String value() default \"default\"; int count() default 1;}// 使用注解class MyClass { @MyAnnotation(value = \"Hello\", count = 3) public void doSomething() { System.out.println(\"执行方法\"); }}
54. 什么是元注解?
答案:用于定义注解的注解,如@Retention
、@Target
等。
实操:演示元注解的使用。
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@interface MyTypeAnnotation { String value();}@MyTypeAnnotation(\"这是一个类注解\")class MyAnnotatedClass { // 类定义}
55. 如何通过反射获取注解信息?
答案:使用getAnnotation()
方法。
实操:通过反射读取注解信息。
import java.lang.reflect.Method;@interface MyAnnotation { String value();}class MyClass { @MyAnnotation(\"测试注解\") public void myMethod() {}}public class AnnotationReflectionDemo { public static void main(String[] args) throws Exception { Method method = MyClass.class.getMethod(\"myMethod\"); MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); if (annotation != null) { System.out.println(\"注解值: \" + annotation.value()); } }}
56. 什么是Java动态代理?
答案:运行时创建代理类的机制,实现AOP等功能。
实操:使用动态代理记录方法调用时间。
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;interface Calculator { int add(int a, int b);}class CalculatorImpl implements Calculator { @Override public int add(int a, int b) { return a + b; }}class TimeHandler implements InvocationHandler { private final Object target; public TimeHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); Object result = method.invoke(target, args); long endTime = System.currentTimeMillis(); System.out.println(method.getName() + \" 执行时间: \" + (endTime - startTime) + \"ms\"); return result; }}public class DynamicProxyDemo { public static void main(String[] args) { Calculator target = new CalculatorImpl(); Calculator proxy = (Calculator) Proxy.newProxyInstance( Calculator.class.getClassLoader(), new Class<?>[]{Calculator.class}, new TimeHandler(target) ); int result = proxy.add(3, 5); System.out.println(\"结果: \" + result); }}
57. 什么是Java模块系统(Java 9+)?
答案:Java 9引入的模块化系统,使用module-info.java定义模块。
实操:创建简单的模块化项目。
// module-info.javamodule mymodule { exports com.example.mypackage; requires java.base; requires java.sql;}// com/example/mypackage/MyClass.javapackage com.example.mypackage;public class MyClass { public static void sayHello() { System.out.println(\"Hello from module!\"); }}
58. 什么是Java 8的方法引用?
答案:简化Lambda表达式的语法,直接引用已有方法。
实操:使用方法引用。
import java.util.Arrays;import java.util.List;public class MethodReferenceDemo { public static void main(String[] args) { List<String> names = Arrays.asList(\"Alice\", \"Bob\", \"Charlie\"); // 使用方法引用 names.forEach(System.out::println); // 等价的Lambda表达式 names.forEach(name -> System.out.println(name)); }}
59. 什么是Java 8的函数式接口?
答案:只包含一个抽象方法的接口,可用@FunctionalInterface注解。
实操:定义和使用函数式接口。
@FunctionalInterfaceinterface MyFunction { int apply(int a, int b);}public class FunctionalInterfaceDemo { public static void main(String[] args) { // 使用Lambda表达式实现函数式接口 MyFunction add = (a, b) -> a + b; int result = add.apply(3, 5); System.out.println(\"结果: \" + result); }}
60. 什么是Java中的本地方法(Native Method)?
答案:用其他语言(如C、C++)实现的Java方法。
实操:声明本地方法。
public class NativeMethodDemo { // 声明本地方法 public native void nativeMethod(); // 加载本地库 static { System.loadLibrary(\"mylib\"); } public static void main(String[] args) { new NativeMethodDemo().nativeMethod(); }}
七、数据库连接
61. 如何连接Java与数据库?
答案:使用JDBC API。
实操:连接MySQL数据库并查询数据。
import java.sql.*;public class JdbcDemo { public static void main(String[] args) { String url = \"jdbc:mysql://localhost:3306/mydb\"; String username = \"root\"; String password = \"password\"; try (Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(\"SELECT * FROM users\")) { while (rs.next()) { System.out.println(rs.getInt(\"id\") + \", \" + rs.getString(\"name\")); } } catch (SQLException e) { e.printStackTrace(); } }}
62. 什么是JDBC?
答案:Java Database Connectivity,用于与数据库交互的API。
实操:使用PreparedStatement插入数据。
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class JdbcPreparedStatementDemo { public static void main(String[] args) { String url = \"jdbc:mysql://localhost:3306/mydb\"; String username = \"root\"; String password = \"password\"; String sql = \"INSERT INTO users (name, age) VALUES (?, ?)\"; try (Connection conn = DriverManager.getConnection(url, username, password); PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, \"李四\"); pstmt.setInt(2, 30); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } }}
63. 什么是数据库连接池?
答案:管理数据库连接的技术,提高性能和资源利用率。
实操:使用HikariCP连接池。
import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;import java.sql.Connection;import java.sql.ResultSet;import java.sql.Statement;public class ConnectionPoolDemo { public static void main(String[] args) { HikariConfig config = new HikariConfig(); config.setJdbcUrl(\"jdbc:mysql://localhost:3306/mydb\"); config.setUsername(\"root\"); config.setPassword(\"password\"); config.setMaximumPoolSize(10); HikariDataSource dataSource = new HikariDataSource(config); try (Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(\"SELECT * FROM users\")) { while (rs.next()) { System.out.println(rs.getString(\"name\")); } } catch (Exception e) { e.printStackTrace(); } }}
64. 什么是事务?
答案:一组不可分割的数据库操作序列。
实操:使用JDBC管理事务。
import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.SQLException;public class TransactionDemo { public static void main(String[] args) { String url = \"jdbc:mysql://localhost:3306/mydb\"; String username = \"root\"; String password = \"password\"; try (Connection conn = DriverManager.getConnection(url, username, password)) { conn.setAutoCommit(false); try (PreparedStatement pstmt1 = conn.prepareStatement(\"UPDATE accounts SET balance = balance - 100 WHERE id = 1\"); PreparedStatement pstmt2 = conn.prepareStatement(\"UPDATE accounts SET balance = balance + 100 WHERE id = 2\")) { pstmt1.executeUpdate(); pstmt2.executeUpdate(); conn.commit(); } catch (SQLException e) { conn.rollback(); e.printStackTrace(); } } catch (SQLException e) { e.printStackTrace(); } }}
65. 什么是SQL注入?如何防止?
答案:通过构造恶意SQL语句攻击数据库,使用PreparedStatement防止。
实操:演示SQL注入及防范。
// 不安全的代码(存在SQL注入风险)String username = \"\' OR \'1\'=\'1\";String sql = \"SELECT * FROM users WHERE username = \'\" + username + \"\'\";// 安全的代码PreparedStatement pstmt = conn.prepareStatement(\"SELECT * FROM users WHERE username = ?\");pstmt.setString(1, username);
66. 什么是ORM?
答案:对象关系映射,将对象模型映射到数据库表。
实操:使用Hibernate实现ORM。
import javax.persistence.*;@Entity@Table(name = \"users\")class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = \"username\") private String username; // getters and setters}
67. 如何使用Java 8的Stream处理数据库结果?
答案:将ResultSet转换为Stream。
实操:将数据库查询结果转换为Stream。
import java.sql.*;import java.util.Spliterator;import java.util.Spliterators;import java.util.stream.Stream;import java.util.stream.StreamSupport;public class JdbcStreamDemo { public static void main(String[] args) { String url = \"jdbc:mysql://localhost:3306/mydb\"; String username = \"root\"; String password = \"password\"; try (Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(\"SELECT * FROM users\")) { Stream<ResultSet> stream = streamResultSet(rs); stream.forEach(row -> { try { System.out.println(row.getString(\"username\")); } catch (SQLException e) { e.printStackTrace(); } }); } catch (SQLException e) { e.printStackTrace(); } } private static Stream<ResultSet> streamResultSet(ResultSet rs) { Spliterator<ResultSet> spliterator = Spliterators.spliteratorUnknownSize( new ResultSetIterator(rs), Spliterator.ORDERED); return StreamSupport.stream(spliterator, false); } static class ResultSetIterator implements java.util.Iterator<ResultSet> { private final ResultSet resultSet; private boolean hasNext; ResultSetIterator(ResultSet resultSet) { this.resultSet = resultSet; try { this.hasNext = resultSet.next(); } catch (SQLException e) { throw new RuntimeException(e); } } @Override public boolean hasNext() { return hasNext; } @Override public ResultSet next() { if (!hasNext) { throw new java.util.NoSuchElementException(); } try { ResultSet current = resultSet; hasNext = resultSet.next(); return current; } catch (SQLException e) { throw new RuntimeException(e); } } }}
68. 什么是数据库索引?
答案:提高数据库查询效率的数据结构。
实操:创建数据库索引。
// 使用JDBC创建索引Statement stmt = conn.createStatement();stmt.executeUpdate(\"CREATE INDEX idx_username ON users (username)\");
69. 什么是存储过程?如何在Java中调用?
答案:预编译的数据库程序,使用CallableStatement调用。
实操:调用存储过程。
try (Connection conn = DriverManager.getConnection(url, username, password); CallableStatement cstmt = conn.prepareCall(\"{call get_user_count(?)}\")) { cstmt.registerOutParameter(1, Types.INTEGER); cstmt.execute(); int count = cstmt.getInt(1); System.out.println(\"用户数量: \" + count);}
70. 如何优化数据库查询性能?
答案:使用索引、优化查询语句、分页等。
实操:分页查询示例。
int pageSize = 10;int pageNumber = 2;int offset = (pageNumber - 1) * pageSize;String sql = \"SELECT * FROM users LIMIT ? OFFSET ?\";try (PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setInt(1, pageSize); pstmt.setInt(2, offset); try (ResultSet rs = pstmt.executeQuery()) { while (rs.next()) { // 处理结果 } }}
八、网络编程
71. 什么是Socket编程?
答案:使用套接字实现网络通信的编程方式。
实操:实现简单的TCP客户端-服务器。
// 服务器端try (ServerSocket serverSocket = new ServerSocket(8080); Socket socket = serverSocket.accept(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { String inputLine; while ((inputLine = in.readLine()) != null) { out.println(\"服务器收到: \" + inputLine); }}// 客户端try (Socket socket = new Socket(\"localhost\", 8080); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { String userInput; while ((userInput = stdIn.readLine()) != null) { out.println(userInput); System.out.println(\"服务器响应: \" + in.readLine()); }}
72. 什么是URL类?
答案:表示统一资源定位符的类。
实操:使用URL读取网页内容。
import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.URL;public class URLDemo { public static void main(String[] args) { try { URL url = new URL(\"https://www.example.com\"); try (BufferedReader reader = new BufferedReader( new InputStreamReader(url.openStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } } catch (Exception e) { e.printStackTrace(); } }}
73. 什么是HTTP客户端?
答案:用于发送HTTP请求的客户端。
实操:使用Java 11的HttpClient发送请求。
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;public class HttpClientDemo { public static void main(String[] args) { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(\"https://api.example.com/data\")) .build(); client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println) .join(); }}
74. 什么是NIO2(AIO)?
答案:异步IO,基于回调机制。
实操:使用AsynchronousSocketChannel实现异步服务器。
import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.AsynchronousServerSocketChannel;import java.nio.channels.AsynchronousSocketChannel;import java.nio.channels.CompletionHandler;public class AIODemo { public static void main(String[] args) throws Exception { AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open() .bind(new InetSocketAddress(8080)); server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void completed(AsynchronousSocketChannel client, Void attachment) { server.accept(null, this); // 继续接受下一个连接 ByteBuffer buffer = ByteBuffer.allocate(1024); client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer buffer) { buffer.flip(); // 处理数据 buffer.clear(); client.read(buffer, buffer, this); } @Override public void failed(Throwable exc, ByteBuffer buffer) { try { client.close(); } catch (Exception e) { e.printStackTrace(); } } }); } @Override public void failed(Throwable exc, Void attachment) { exc.printStackTrace(); } }); Thread.sleep(1000000); // 保持服务器运行 }}
75. 什么是WebSocket?
答案:双向通信的网络协议。
实操:使用Java API实现WebSocket客户端。
import javax.websocket.*;import java.net.URI;@ClientEndpointpublic class WebSocketClient { private Session session; public WebSocketClient(String uri) { try { WebSocketContainer container = ContainerProvider.getWebSocketContainer(); session = container.connectToServer(this, URI.create(uri)); } catch (Exception e) { e.printStackTrace(); } } @OnOpen public void onOpen(Session session) { System.out.println(\"连接打开: \" + session.getId()); } @OnMessage public void onMessage(String message) { System.out.println(\"收到消息: \" + message); } @OnClose public void onClose(Session session, CloseReason reason) { System.out.println(\"连接关闭: \" + reason); } public void sendMessage(String message) { session.getAsyncRemote().sendText(message); }}
76. 什么是防火墙?
答案:网络安全设备,控制网络流量。
实操:配置简单的防火墙规则。
# 使用iptables阻止外部访问8080端口iptables -A INPUT -p tcp --dport 8080 -j DROP
77. 什么是代理服务器?
答案:位于客户端和服务器之间的中间服务器。
实操:通过代理服务器发送HTTP请求。
import java.net.*;import java.io.*;public class ProxyDemo { public static void main(String[] args) { try { Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(\"proxy.example.com\", 8080)); URL url = new URL(\"https://www.example.com\"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy); try (BufferedReader reader = new BufferedReader( new InputStreamReader(connection.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } } catch (Exception e) { e.printStackTrace(); } }}
78. 什么是网络协议?
答案:网络通信的规则和标准。
实操:实现简单的UDP通信。
// 发送方try (DatagramSocket socket = new DatagramSocket()) { String message = \"Hello, UDP!\"; byte[] buffer = message.getBytes(); InetAddress address = InetAddress.getByName(\"localhost\"); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 8888); socket.send(packet);}// 接收方try (DatagramSocket socket = new DatagramSocket(8888)) { byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); socket.receive(packet); String message = new String(packet.getData(), 0, packet.getLength()); System.out.println(\"收到: \" + message);}
79. 什么是RESTful API?
答案:基于HTTP协议的API设计风格。
实操:使用Spring Boot创建简单的REST API。
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;@SpringBootApplication@RestControllerpublic class RestApiDemo { public static void main(String[] args) { SpringApplication.run(RestApiDemo.class, args); } @GetMapping(\"/hello/{name}\") public String sayHello(@PathVariable String name) { return \"Hello, \" + name + \"!\"; }}
80. 什么是JSON?如何在Java中处理JSON?
答案:轻量级数据交换格式,使用Jackson等库处理。
实操:使用Jackson解析JSON。
import com.fasterxml.jackson.databind.ObjectMapper;public class JsonDemo { public static void main(String[] args) { String json = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":30}\"; try { ObjectMapper mapper = new ObjectMapper(); Person person = mapper.readValue(json, Person.class); System.out.println(person.getName() + \", \" + person.getAge()); } catch (Exception e) { e.printStackTrace(); } }}class Person { private String name; private int age; // getters and setters}
九、设计模式
81. 什么是单例模式?
答案:确保一个类只有一个实例。
实操:实现线程安全的单例模式。
public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; }}
82. 什么是工厂模式?
答案:定义创建对象的接口,由子类决定实例化哪个类。
实操:实现简单工厂模式。
interface Shape { void draw();}class Circle implements Shape { @Override public void draw() { System.out.println(\"绘制圆形\"); }}class Rectangle implements Shape { @Override public void draw() { System.out.println(\"绘制矩形\"); }}class ShapeFactory { public Shape getShape(String shapeType) { if (shapeType == null) { return null; } if (shapeType.equalsIgnoreCase(\"CIRCLE\")) { return new Circle(); } else if (shapeType.equalsIgnoreCase(\"RECTANGLE\")) { return new Rectangle(); } return null; }}
83. 什么是观察者模式?
答案:对象间一对多的依赖关系。
实操:实现简单的观察者模式。
import java.util.ArrayList;import java.util.List;interface Observer { void update(String message);}class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) { this.name = name; } @Override public void update(String message) { System.out.println(name + \" 收到消息: \" + message); }}interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(String message);}class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>(); @Override public void registerObserver(Observer observer) { observers.add(observer); } @Override public void removeObserver(Observer observer) { observers.remove(observer); } @Override public void notifyObservers(String message) { for (Observer observer : observers) { observer.update(message); } }}
84. 什么是装饰器模式?
答案:动态地给对象添加额外职责。
实操:实现咖啡装饰器。
interface Beverage { String getDescription(); double cost();}class Espresso implements Beverage { @Override public String getDescription() { return \"浓缩咖啡\"; } @Override public double cost() { return 1.99; }}abstract class CondimentDecorator implements Beverage { protected Beverage beverage; public CondimentDecorator(Beverage beverage) { this.beverage = beverage; }}class Milk extends CondimentDecorator { public Milk(Beverage beverage) { super(beverage); } @Override public String getDescription() { return beverage.getDescription() + \", 牛奶\"; } @Override public double cost() { return beverage.cost() + 0.3; }}
85. 什么是策略模式?
答案:定义一系列算法并封装,使它们可以互相替换。
实操:实现支付策略。
interface PaymentStrategy { void pay(double amount);}class CreditCardStrategy implements PaymentStrategy { private String cardNumber; private String cvv; public CreditCardStrategy(String cardNumber, String cvv) { this.cardNumber = cardNumber; this.cvv = cvv; } @Override public void pay(double amount) { System.out.println(\"使用信用卡支付: \" + amount); }}class PayPalStrategy implements PaymentStrategy { private String email; public PayPalStrategy(String email) { this.email = email; } @Override public void pay(double amount) { System.out.println(\"使用PayPal支付: \" + amount); }}class ShoppingCart { private PaymentStrategy paymentStrategy; public void setPaymentStrategy(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void checkout(double amount) { paymentStrategy.pay(amount); }}
86. 什么是适配器模式?
答案:将一个类的接口转换成客户希望的另一个接口。
实操:实现电源适配器。
interface EuropeanPlug { void plugInEuropeanSocket();}class EuropeanDevice implements EuropeanPlug { @Override public void plugInEuropeanSocket() { System.out.println(\"欧洲设备插入欧洲插座\"); }}interface USAPlug { void plugInUSASocket();}class USADevice implements USAPlug { @Override public void plugInUSASocket() { System.out.println(\"美国设备插入美国插座\"); }}class PlugAdapter implements EuropeanPlug { private USAPlug usaPlug; public PlugAdapter(USAPlug usaPlug) { this.usaPlug = usaPlug; } @Override public void plugInEuropeanSocket() { usaPlug.plugInUSASocket(); System.out.println(\"使用适配器转换为欧洲插头\"); }}
87. 什么是模板方法模式?
答案:定义算法骨架,将一些步骤延迟到子类实现。
实操:实现烹饪模板。
abstract class CookingRecipe { public final void cook() { prepareIngredients(); cookIngredients(); serve(); } protected abstract void prepareIngredients(); protected abstract void cookIngredients(); protected void serve() { System.out.println(\"上菜\"); }}class PastaRecipe extends CookingRecipe { @Override protected void prepareIngredients() { System.out.println(\"准备意大利面和酱料\"); } @Override protected void cookIngredients() { System.out.println(\"煮意大利面,加热酱料\"); }}
88. 什么是责任链模式?
答案:将请求的发送者和接收者解耦。
实操:实现请假审批链。
abstract class Approver { protected Approver successor; public void setSuccessor(Approver successor) { this.successor = successor; } public abstract void processRequest(int days);}class TeamLeader extends Approver { @Override public void processRequest(int days) { if (days <= 3) { System.out.println(\"团队领导批准请假 \" + days + \" 天\"); } else if (successor != null) { successor.processRequest(days); } }}class DepartmentManager extends Approver { @Override public void processRequest(int days) { if (days <= 7) { System.out.println(\"部门经理批准请假 \" + days + \" 天\"); } else if (successor != null) { successor.processRequest(days); } }}
89. 什么是状态模式?
答案:允许对象在内部状态改变时改变它的行为。
实操:实现电梯状态。
interface ElevatorState { void openDoor(); void closeDoor(); void goUp(); void goDown();}class IdleState implements ElevatorState { private Elevator elevator; public IdleState(Elevator elevator) { this.elevator = elevator; } @Override public void openDoor() { System.out.println(\"电梯门打开\"); elevator.setState(elevator.getDoorOpenState()); } @Override public void closeDoor() { System.out.println(\"电梯门已关闭\"); } @Override public void goUp() { System.out.println(\"电梯上升\"); elevator.setState(elevator.getMovingUpState()); } @Override public void goDown() { System.out.println(\"电梯下降\"); elevator.setState(elevator.getMovingDownState()); }}class Elevator { private ElevatorState doorOpenState; private ElevatorState doorClosedState; private ElevatorState movingUpState; private ElevatorState movingDownState; private ElevatorState currentState; public Elevator() { doorOpenState = new DoorOpenState(this); doorClosedState = new DoorClosedState(this); movingUpState = new MovingUpState(this); movingDownState = new MovingDownState(this); currentState = doorClosedState; } // getters and setters}
90. 什么是建造者模式?
答案:将一个复杂对象的构建与表示分离。
实操:实现电脑建造者。
class Computer { private String cpu; private String ram; private String storage; public void setCpu(String cpu) { this.cpu = cpu; } public void setRam(String ram) { this.ram = ram; } public void setStorage(String storage) { this.storage = storage; } @Override public String toString() { return \"CPU: \" + cpu + \", RAM: \" + ram + \", Storage: \" + storage; }}interface ComputerBuilder { void buildCpu(); void buildRam(); void buildStorage(); Computer getComputer();}class GamingComputerBuilder implements ComputerBuilder { private Computer computer; public GamingComputerBuilder() { this.computer = new Computer(); } @Override public void buildCpu() { computer.setCpu(\"Intel i9\"); } @Override public void buildRam() { computer.setRam(\"32GB\"); } @Override public void buildStorage() { computer.setStorage(\"1TB SSD\"); } @Override public Computer getComputer() { return computer; }}class ComputerDirector { private ComputerBuilder builder; public ComputerDirector(ComputerBuilder builder) { this.builder = builder; } public Computer constructComputer() { builder.buildCpu(); builder.buildRam(); builder.buildStorage(); return builder.getComputer(); }}
十、性能优化
91. 如何优化Java应用程序的性能?
答案:从代码、JVM参数、数据库等多方面优化。
实操:使用StringBuilder替代String拼接。
// 优化前String result = \"\";for (int i = 0; i < 1000; i++) { result += i; // 会创建大量临时对象}// 优化后StringBuilder sb = new StringBuilder();for (int i = 0; i < 1000; i++) { sb.append(i); // 性能更好}String result = sb.toString();
92. 什么是JVM调优?
答案:调整JVM参数以提高性能。
实操:设置堆内存大小。
java -Xms512m -Xmx1024m MyApp
93. 什么是垃圾回收(GC)?
答案:自动回收不再使用的内存。
实操:监控GC情况。
java -XX:+PrintGCDetails -XX:+PrintGCTimeStamps MyApp
94. 如何分析内存泄漏?
答案:使用工具如VisualVM、MAT等。
实操:使用jstat监控堆内存使用。
jstat -gc <pid> 1000 10
95. 什么是对象池?
答案:重用对象以减少创建和销毁开销。
实操:实现简单的对象池。
import java.util.concurrent.ConcurrentLinkedQueue;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ObjectPool<T> { private ConcurrentLinkedQueue<T> pool; private ScheduledExecutorService executorService; public ObjectPool(final int minObjects) { // 初始化对象池 initialize(minObjects); } public ObjectPool(final int minObjects, final int maxObjects, final long validationInterval) { // 初始化对象池 initialize(minObjects); // 定时检查,维持对象池最小大小 executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(() -> { int size = pool.size(); if (size < minObjects) { int sizeToBeAdded = minObjects - size; for (int i = 0; i < sizeToBeAdded; i++) { pool.add(createObject()); } } else if (size > maxObjects) { int sizeToBeRemoved = size - maxObjects; for (int i = 0; i < sizeToBeRemoved; i++) { pool.poll(); } } }, validationInterval, validationInterval, TimeUnit.SECONDS); } public T borrowObject() { T object; if ((object = pool.poll()) == null) { object = createObject(); } return object; } public void returnObject(T object) { if (object == null) { return; } this.pool.offer(object); } public void shutdown() { if (executorService != null) { executorService.shutdown(); } } private void initialize(final int minObjects) { pool = new ConcurrentLinkedQueue<>(); for (int i = 0; i < minObjects; i++) { pool.add(createObject()); } } protected T createObject() { // 由子类实现创建对象的逻辑 return null; }}
96. 什么是线程池?
答案:管理线程的创建和复用。
实操:自定义线程池。
import java.util.concurrent.*;public class CustomThreadPoolDemo { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor( 5, // 核心线程数 10, // 最大线程数 60, // 线程空闲时间 TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), // 任务队列 Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 ); // 提交任务 for (int i = 0; i < 20; i++) { final int taskId = i; executor.submit(() -> { System.out.println(\"执行任务: \" + taskId + \", 线程: \" + Thread.currentThread().getName()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); }}
97. 如何优化数据库查询?
答案:使用索引、优化SQL语句、避免N+1查询等。
实操:使用EXPLAIN分析查询。
EXPLAIN SELECT * FROM users WHERE age > 30;
98. 什么是缓存?如何在Java中实现缓存?
答案:临时存储数据以提高访问速度。
实操:使用Guava Cache实现本地缓存。
import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.TimeUnit;public class CacheDemo { private static Cache<String, String> cache = CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .build(); public static String getData(String key) { String data = cache.getIfPresent(key); if (data == null) { data = fetchFromDatabase(key); cache.put(key, data); } return data; } private static String fetchFromDatabase(String key) { // 从数据库获取数据 return \"Data for \" + key; }}
99. 什么是懒加载?
答案:延迟加载数据直到需要使用。
实操:实现懒加载单例。
public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static synchronized LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; }}
100. 如何进行代码性能分析?
答案:使用工具如JProfiler、YourKit等。
实操:使用Java Mission Control进行性能分析。
jcmd <pid> JFR.start duration=60s filename=recording.jfr
十一、安全
101. 什么是SQL注入?如何防止?
答案:通过构造恶意SQL语句攻击数据库。
实操:使用PreparedStatement防止SQL注入。
// 不安全的代码String sql = \"SELECT * FROM users WHERE username = \'\" + username + \"\' AND password = \'\" + password + \"\'\";// 安全的代码PreparedStatement pstmt = conn.prepareStatement(\"SELECT * FROM users WHERE username = ? AND password = ?\");pstmt.setString(1, username);pstmt.setString(2, password);
102. 什么是XSS攻击?如何防止?
答案:跨站脚本攻击,注入恶意脚本。
实操:对用户输入进行转义。
import org.owasp.encoder.Encode;public class XSSPrevention { public static String escapeHTML(String input) { return Encode.forHtml(input); }}
103. 什么是CSRF攻击?如何防止?
答案:跨站请求伪造,冒充合法用户。
实操:使用CSRF令牌。
// 生成CSRF令牌String token = UUID.randomUUID().toString();session.setAttribute(\"csrfToken\", token);// 在表单中包含令牌<form> <input type=\"hidden\" name=\"csrfToken\" value=\"${csrfToken}\"> <!-- 其他表单字段 --></form>// 验证令牌if (!token.equals(session.getAttribute(\"csrfToken\"))) { throw new SecurityException(\"Invalid CSRF token\");}
104. 如何进行密码加密?
答案:使用哈希算法加随机盐。
实操:使用BCrypt加密密码。
import org.mindrot.jbcrypt.BCrypt;public class PasswordHashing { public static String hashPassword(String password) { return BCrypt.hashpw(password, BCrypt.gensalt()); } public static boolean checkPassword(String password, String hashedPassword) { return BCrypt.checkpw(password, hashedPassword); }}
105. 什么是HTTPS?如何配置?
答案:HTTP的安全版本,使用SSL/TLS加密。
实操:配置Spring Boot应用使用HTTPS。
server: port: 8443 ssl: key-store: classpath:keystore.p12 key-store-password: yourpassword key-store-type: PKCS12 key-alias: tomcat
106. 什么是JWT?如何使用?
答案:JSON Web Token,用于安全传输信息。
实操:生成和验证JWT。
import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;public class JwtUtil { private static final String SECRET_KEY = \"yoursecretkey\"; private static final long EXPIRATION_TIME = 86400000; // 24小时 public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String validateToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJ---